Mare Bits Locker is a way to lock-up your ERC20, ERC721, or ERC1155 tokens and keep them safe from that waifu thief Brad. The contract issues a non-fungible token (NFT) that represents your deposit and allows whoever owns that token after a pre-determined length of time to withdraw the locked funds. Once locked, your tokens cannot be withdrawn until the lock period has expired no matter what. So, be careful!
This was created to facilitate the locking of liquidity tokens as part of the launch of Mare Bits ($MARE). For more information on that project, see https://mare.biz/. In order to make the code easily reviewable by others, I've released it here.
This should work for all tokens that implement either the ERC20, ERC721, or ERC1155 interfaces, including ERC777.
In order to use the Mare Bits Locker, your wallet must have a $MARE balance greater than zero.
Here are the deployed contract addresses. Please note, Etherscan/Polygonscan make interacting with verified contracts very easy and all of these are verified. Click the link below, then click on Read Contract
to get data and Write Contract
to execute functions that modify the block chain (you will need a wallet like Metamask if you are using the Write Contract
functions).
-
Ethereum:
- Mare Bits Locker: (TBD)
- Mare Bits Locker Account: (TBD)
- Mare Bits Locker Token: (TBD)
- Mare Bits Vault: (TBD)
-
Polygon:
- Mare Bits Locker: 0xdFcB170bEa5b1B970574b8cCd0347A095256c4A8
- Mare Bits Locker Account: 0x7c20bfda6ba2cd5ca85b952696e279a2efcd5ff2
- Mare Bits Locker Token: 0xc12d120e3973e7bac07e1802ca0ea30676451642
- Mare Bits Vault: 0x3d41144b7236fb2119c52546d6f5df15c0c316a8
-
Ropsten (test network):
- Mare Bits Locker: 0xe8fFc80a8D5c07Eb9Cd52AbF1a081b588d663414
- Mare Bits Locker Account: 0xfc0c341d8522f896e569bce3641a873ae8dbe506
- Mare Bits Locker Token: 0x78910d0a3b750462e82699a40afec7c10332ec5c
- Mare Bits Vault: 0x1ef0433cc1646451b038617b9963f2afa6428cc1
(If you wish to use the Ropsten contract and need $MARE, please send your wallet address to [email protected] and I will send you some.)
Interaction will primarily be with the Mare Bits Locker, Mare Bits Locker Account, and Mare Bits Locker Token contracts. The Mare Bits Vault contract just holds deposits and doesn't offer much public functionality.
accounts() returns (IMarebitsLockerAccount)
- Returns the address associated with the Mare Bits Locker Account contract.
bestPony() returns (string)
- Returns the best pony.
extendLock(uint256 accountId, uint64 unlockTime) returns (uint256)
- Sets the lock time for account
accountId
tounlockTime
(in seconds since UNIX epoch). The new unlock time must be greater than the existing unlock time for the account (will throwTimeOutOfBounds
if not). Emits theTokensLocked
event and returns theaccountId
when successful. getAccount(uint256 accountId) returns (Account.Info)
- Returns the account details for the account
accountId
. These details include theaccountId
, theamount
of tokens locked, thetokenId
of the token locked, thetokenContract
address, thetokenType
locked, theunlockTime
, whether or not the locker tokenisBurned
, and whether or not the locker tokenisRedeemed
. lockerToken() returns (IMarebitsLockerToken)
- Returns the address associated with the Mare Bits Locker Token contract.
lockTokens(Token.Type tokenType, address tokenContract, uint256 tokenId, uint256 amount, uint64 unlockTime) returns (uint256)
- Locks
amount
tokens of thetokenType
token deployed at thetokenContract
address with the token IDtokenId
for a period represented byunlockTime
(in seconds since UNIX epoch). ThetokenId
is ignored for ERC-20 tokens and theamount
must be1
for ERC-721 tokens. Emits theTokensLocked
event and returns the newly createdaccountId
when successful. mareBitsToken() returns (IERC20)
- Returns the address associated with the Mare Bits token contract. (This function is private in the Polygon contract.)
redeemToken(uint256 accountId)
- Redeems the token for the account
accountId
, returning the locked tokens to the owner ofaccountId
. This will throw aTimeOutOfBounds
error if attempted beforeunlockTime
has expired. Emits theTokenRedeemed
event when successful. supportsInterface(bytes4 interfaceId) returns (bool)
- See ERC-165.
vault() returns (IMarebitsVault)
- Returns the address associated with the Mare Bits Vault contract.
TokensLocked(uint256 indexed accountId, address indexed owner, uint256 amount, address tokenContract, uint256 tokenId, Token.Type tokenType, uint64 unlockTime)
- Emitted whenever a new locker is created or whenever the
unlockTime
for an existing locker has been extended. TokenRedeemed(uint256 indexed accountId, address indexed owner, uint256 amount, address tokenContract, uint256 tokenId, Token.Type tokenType)
- Emitted whenever a locker token is redeemed and the deposited tokens are returned to the
owner
.
InsufficientBalance(uint256 required, uint256 available)
- Thrown when the required balance is less than the available balance.
InvalidAmount(string reason)
- Thrown when an invalid amount is entered. The
reason
should contain the reason why the amount was invalid. InvalidCaller()
- Thrown when called by an invalid caller (such as a contract instead of a real wallet).
InvalidTokenType(Token.Type tokenType)
- Thrown when the
tokenType
is not valid. Must be 1 for ERC-1155, 2 for ERC-20, or 3 for ERC-721. LockedAccount(uint64 expiresAt, uint64 currentTime)
- Thrown when attempting to call
redeemToken
for an account that is still locked.expiresAt
is the time when the lock expires (in seconds since UNIX epoch) andcurrentTime
is the current block time stamp (in seconds since UNIX epoch). NeedsMoreMARE(address wallet)
- Thrown when someone attempts to interact with this contract who does not hodl $MARE. You must have a balance greater than 0.
NonexistentAccount(uint256 accountId)
- Thrown when the account
accountId
doesn't exist. NotTokenOwner(uint256 tokenId, address claimedOwner, address actualOwner)
- Thrown when attempting to lock the token
tokenId
byclaimedOwner
when the actual owner isactualOwner
. TimeOutOfBounds(uint64 given, uint64 minimum, uint64 maximum)
- Thrown when the
given
time does not fall within the range specified byminimum
andmaximum
. UnapprovedTokenTransfer(address tokenAddress, string approvalFunction)
- Thrown when attempting to transfer tokens for token contract
tokenAddress
. TheapprovalFunction
tells you what function needs to be run on thetokenAddress
contract to approve the transfer. ZeroAmountGiven()
- Thrown when a zero amount is passed.
Token.Type
- Is an enumerated value represented internally as a
uint8
where:0
meansUNDEFINED
1
meansERC-1155
2
meansERC-20
3
meansERC-721
Account.Info
- Is a data structure (or object) with the following members:
uint256 accountId
- The account ID
uint256 amount
- The amount of tokens locked in the account
uint256 tokenId
- The token ID for the tokens locked in the account (only meaningful for ERC-1155 and ERC-721 tokens, will be 0 for ERC-20 tokens)
address tokenContract
- The address of the token contract for the locked tokens
uint64 unlockTime
- The time after which the account token can be redeemed to withdraw the locked token balance (in seconds since UNIX epoch)
bool isBurned
- True when the account token has been burned; otherwise, false
bool isRedeemed
- True when the tokens locked by the account have been redeemed; otherwise, false
bestPony() returns (string)
- Returns the best pony.
getAccount(uint256 accountId) returns (Account.Info)
- Returns the account details for the account
accountId
. These details include theaccountId
, theamount
of tokens locked, thetokenId
of the token locked, thetokenContract
address, thetokenType
locked, theunlockTime
, whether or not the locker tokenisBurned
, and whether or not the locker tokenisRedeemed
. supportsInterface(bytes4 interfaceId) returns (bool)
- See ERC-165.
NonexistentAccount(uint256 accountId)
- Thrown when the account
accountId
doesn't exist.
This contract represents the ERC-721 token issued when tokens are locked. As such, it extends all the functions and events from the ERC-721 specification.
approve(address to, uint256 tokenId)
- Gives permission to
to
to transfer tokentokenId
to another account. The approval is cleared when the token is transferred. Only a single account can be approved at a time, so approving the zero address clears previous approvals. Emits anApproval
event when successful. balanceOf(address owner) returns (uint256)
- Returns the number of Mare Bits Locker tokens held by address
owner
. bestPony() returns (string)
- Returns the best pony.
burn(uint256 tokenId)
- Can only be called by the owner of the token
tokenId
or someone the owner has approved. This will burn the locker token, in effect sending it to the zero address. If this is called, the token will disappear and any tokens locked in the locker will be unredeemable! Emits aTransfer
event when successful. getApproved(uint256 tokenId) returns (address)
- Returns the account approved to transfer token
tokenId
. isApprovedForAll(address owner, address operator) returns (bool)
- Returns true if the
operator
is allowed to manage all of the assets ofowner
. name() returns (string)
- Returns the general name of this token (Mare Bits Locker Token).
ownerOf(uint256 tokenId) returns (address)
- Returns the address that owns the token
tokenId
. safeTransferFrom(address from, address to, uint256 tokenId)
- Safely transfers token
tokenId
fromfrom
toto
, checking first that contract recipients are aware of the ERC-721 protocol to prevent tokens from being forever locked. Emits aTransfer
event when successful. setApprovalForAll(address operator, bool _approved)
- Approve or remove
operator
as an operator for the caller. Operators can calltransferFrom
orsafeTransferFrom
for any token owned by the caller. Emits anApprovalForAll
event when successful. supportsInterface(bytes4 interfaceId) returns (bool)
- See ERC-165.
symbol() returns (string)
- Returns the general symbol of this token (๐โโ๏ธ๐๐ช).
tokenByIndex(uint256 index) returns (uint256)
- REturns a token ID at a given
index
of all Mare Bit Locker Tokens. Use along withtotalSupply
to enumerate all tokens. tokenOfOwnerByIndex(address owner, uint256 index) returns (uint256)
- Returns a token ID owned by
owner
at a givenindex
of its token list. Use along withbalanceOf
to enumerate all ofowner
's tokens. tokenURI(uint256 tokenId)
- Returns the URI containing metadata for the token
tokenId
. This is used by sites to display metadata for this NFT. totalSupply() returns (uint256)
- Returns the total amount of Mare Bit Locker Tokens.
transferFrom(address from, address to, uint256 tokenId)
- Transfers token
tokenId
fromfrom
toto
. Emits aTransfer
event when successful.
Approval(address owner, address approved, uint256 tokenId)
- Emitted when
owner
enabledapproved
to manager the tokentokenId
. ApprovalForAll(address owner, address operator, bool approved)
- Emitted when
owner
enables or disables (approved
)operator
to manager all of its assets. Transfer(address from, address to, uint256 tokenId)
- Emitted when token
tokenId
is transferred fromfrom
toto
. URI(string value, uint256 indexed id)
- Emitted when the URI of the token
id
has changed tovalue
.
NotApprovedOrOwner(uint256 tokenId)
- Thrown when attempted to transfer a token the caller does not own or is not approved to transfer.
NotLockerOwner(address claimedOwner, address actualOwner)
- Thrown when attempted to make a call that only the owner of this contract's owner can make.
bestPony() returns (string)
- Returns the best pony.
onERC1155BatchReceived(address operator, address from, uint256[] ids, uint256[] values, bytes data) returns (bytes4)
- Handles the receipt of multiple ERC-1155 token types. This function is called at the end of a
safeBatchTransferFrom
after the balances have been updated. It returns its Solidity selector to confirm the token transfers. onERC1155Received(address operator, address from, uint256 id, uint256 value, bytes data) returns (bytes4)
- Handles the receipt of a single ERC-1155 token type. This function is called at the end of a
safeTransferFrom
after the balance has been updated. It returns its Solidity selector to confirm the token transfer. onERC721Received(address operator, address from, uint256 tokenId, bytes data) returns (bytes4)
- Whenever an ERC-721
tokenId
is transferred to this contract viasafeTransferFrom
byoperator
fromfrom
, this function is called. It returns its Solidity selector to confirm the token transfer. supportsInterface(bytes4 interfaceId) returns (bool)
- See ERC-165.