Address Contract Verified
Address
0x904f36d74bED2Ef2729Eaa1c7A5B70dEA2966a02
Balance
0 ETH
Nonce
1
Code Size
17060 bytes
Creator
0x3031303B...b3a1 at tx 0x118a01c5...8e563b
Indexed Transactions
0
Contract Bytecode
17060 bytes
0x608060405234801561001057600080fd5b50600436106101c45760003560e01c80636fcfff45116100f9578063b4b5ea5711610097578063dd62ed3e11610071578063dd62ed3e14610533578063e7a324dc14610563578063f1127ed814610581578063fca3b5aa146105b2576101c4565b8063b4b5ea57146104cb578063c3cda520146104fb578063d505accf14610517576101c4565b8063782d6fe1116100d3578063782d6fe11461041d5780637ecebe001461044d57806395d89b411461047d578063a9059cbb1461049b576101c4565b80636fcfff451461039f57806370a08231146103cf57806376c71ca1146103ff576101c4565b806330b36cef1161016657806340c10f191161014057806340c10f1914610319578063587cde1e146103355780635c11d62f146103655780635c19a95c14610383576101c4565b806330b36cef146102bf578063313ce567146102dd5780633644e515146102fb576101c4565b806318160ddd116101a257806318160ddd1461023557806320606b701461025357806323b872dd1461027157806330adf81f146102a1576101c4565b806306fdde03146101c957806307546172146101e7578063095ea7b314610205575b600080fd5b6101d16105ce565b6040516101de9190612ca6565b60405180910390f35b6101ef610607565b6040516101fc9190612d09565b60405180910390f35b61021f600480360381019061021a9190612d8b565b61062d565b60405161022c9190612de6565b60405180910390f35b61023d6107b9565b60405161024a9190612e10565b60405180910390f35b61025b6107bf565b6040516102689190612e44565b60405180910390f35b61028b60048036038101906102869190612e5f565b6107e3565b6040516102989190612de6565b60405180910390f35b6102a9610a65565b6040516102b69190612e44565b60405180910390f35b6102c7610a89565b6040516102d49190612e10565b60405180910390f35b6102e5610a8f565b6040516102f29190612ece565b60405180910390f35b610303610a94565b6040516103109190612e44565b60405180910390f35b610333600480360381019061032e9190612d8b565b610b2b565b005b61034f600480360381019061034a9190612ee9565b610f11565b60405161035c9190612d09565b60405180910390f35b61036d610f44565b60405161037a9190612f35565b60405180910390f35b61039d60048036038101906103989190612ee9565b610f4c565b005b6103b960048036038101906103b49190612ee9565b610f59565b6040516103c69190612f35565b60405180910390f35b6103e960048036038101906103e49190612ee9565b610f7c565b6040516103f69190612e10565b60405180910390f35b610407610feb565b6040516104149190612ece565b60405180910390f35b61043760048036038101906104329190612d8b565b610ff0565b6040516104449190612f77565b60405180910390f35b61046760048036038101906104629190612ee9565b611429565b6040516104749190612e10565b60405180910390f35b610485611441565b6040516104929190612ca6565b60405180910390f35b6104b560048036038101906104b09190612d8b565b61147a565b6040516104c29190612de6565b60405180910390f35b6104e560048036038101906104e09190612ee9565b6114b7565b6040516104f29190612f77565b60405180910390f35b61051560048036038101906105109190612fea565b6115ae565b005b610531600480360381019061052c9190613077565b6117e2565b005b61054d60048036038101906105489190613119565b611bbe565b60405161055a9190612e10565b60405180910390f35b61056b611c6b565b6040516105789190612e44565b60405180910390f35b61059b60048036038101906105969190613185565b611c8f565b6040516105a99291906131c5565b60405180910390f35b6105cc60048036038101906105c79190612ee9565b611ce8565b005b6040518060400160405280600981526020017f426c75656265727279000000000000000000000000000000000000000000000081525081565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830361066b576bffffffffffffffffffffffff9050610690565b61068d836040518060600160405280602e8152602001614140602e9139611e86565b90505b80600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836bffffffffffffffffffffffff166040516107a69190612e10565b60405180910390a3600191505092915050565b60005481565b7f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6000803390506000600360008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046bffffffffffffffffffffffff16905060006108a6856040518060600160405280602e8152602001614140602e9139611e86565b90508673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561090057506bffffffffffffffffffffffff8016826bffffffffffffffffffffffff1614155b15610a4c57600061092a83836040518060800160405280604681526020016140bb60469139611ee4565b905080600360008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836bffffffffffffffffffffffff16604051610a429190612e10565b60405180910390a3505b610a57878783611f5e565b600193505050509392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60025481565b601281565b60007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a8666040518060400160405280600981526020017f426c75656265727279000000000000000000000000000000000000000000000081525080519060200120610afc61233d565b30604051602001610b1094939291906131ee565b60405160208183030381529060405280519060200120905090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610bbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bb2906132a5565b60405180910390fd5b600254421015610c00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bf790613337565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610c6f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c66906133c9565b60405180910390fd5b6301e1338063ffffffff1642610c859190613418565b6002819055506000610caf826040518060600160405280602b8152602001614244602b9139611e86565b90506064600260ff16600054610cc5919061344c565b610ccf91906134d5565b821115610d11576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d0890613578565b60405180910390fd5b610d4082600054610d229190613418565b6040518060600160405280603081526020016141ab60309139611e86565b6bffffffffffffffffffffffff16600081905550610dce600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046bffffffffffffffffffffffff1682604051806060016040528060328152602001613ffc6032913961234a565b600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610e999190612e10565b60405180910390a3610f0c6000600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836123c9565b505050565b60056020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6301e1338081565b610f5633826126d6565b50565b60076020528060005260406000206000915054906101000a900463ffffffff1681565b6000600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff169050919050565b600281565b6000438210611034576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161102b9061360a565b60405180910390fd5b6000600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900463ffffffff16905060008163ffffffff16036110a0576000915050611423565b82600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006001846110ef919061362a565b63ffffffff1663ffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16116111b457600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600183611176919061362a565b63ffffffff1663ffffffff16815260200190815260200160002060000160049054906101000a90046bffffffffffffffffffffffff16915050611423565b82600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008063ffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff161115611235576000915050611423565b600080600183611245919061362a565b90505b8163ffffffff168163ffffffff1611156113a55760006002838361126c919061362a565b6112769190613662565b82611281919061362a565b90506000600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008363ffffffff1663ffffffff1681526020019081526020016000206040518060400160405290816000820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160049054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff1681525050905086816000015163ffffffff160361137457806020015195505050505050611423565b86816000015163ffffffff16101561138e5781935061139e565b60018261139b919061362a565b92505b5050611248565b600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008363ffffffff1663ffffffff16815260200190815260200160002060000160049054906101000a90046bffffffffffffffffffffffff1693505050505b92915050565b60086020528060005260406000206000915090505481565b6040518060400160405280600381526020017f424c42000000000000000000000000000000000000000000000000000000000081525081565b60008061149f836040518060600160405280602f815260200161405f602f9139611e86565b90506114ac338583611f5e565b600191505092915050565b600080600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900463ffffffff16905060008163ffffffff16116115215760006115a6565b600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600060018361156f919061362a565b63ffffffff1663ffffffff16815260200190815260200160002060000160049054906101000a90046bffffffffffffffffffffffff165b915050919050565b60007fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf8787876040516020016115e79493929190613693565b6040516020818303038152906040528051906020012090506000611609610a94565b8260405160200161161b929190613750565b6040516020818303038152906040528051906020012090506000600182878787604051600081526020016040526040516116589493929190613787565b6020604051602081039080840390855afa15801561167a573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036116f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116ec9061383e565b60405180910390fd5b600860008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906117459061385e565b91905055881461178a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161178190613918565b60405180910390fd5b864211156117cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c4906139aa565b60405180910390fd5b6117d7818a6126d6565b505050505050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff860361181f576bffffffffffffffffffffffff9050611844565b611841866040518060600160405280602d815260200161408e602d9139611e86565b90505b60007f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9898989600860008e73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008154809291906118ba9061385e565b919050558a6040516020016118d4969594939291906139ca565b60405160208183030381529060405280519060200120905060006118f6610a94565b82604051602001611908929190613750565b6040516020818303038152906040528051906020012090506000600182888888604051600081526020016040526040516119459493929190613787565b6020604051602081039080840390855afa158015611967573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036119e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119d990613a9d565b60405180910390fd5b8a73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611a50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a4790613b2f565b60405180910390fd5b87421115611a93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8a90613bc1565b60405180910390fd5b83600360008d73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008c73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508973ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925866bffffffffffffffffffffffff16604051611ba99190612e10565b60405180910390a35050505050505050505050565b6000600360008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff16905092915050565b7fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b6006602052816000526040600020602052806000526040600020600091509150508060000160009054906101000a900463ffffffff16908060000160049054906101000a90046bffffffffffffffffffffffff16905082565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d78576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d6f90613c79565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603611de7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dde90613d0b565b60405180910390fd5b7f3b0007eb941cf645526cbb3a4fdaecda9d28ce4843167d9263b536a1f1edc0f6600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682604051611e3a929190613d2b565b60405180910390a180600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b60006c0100000000000000000000000083108290611eda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ed19190612ca6565b60405180910390fd5b5082905092915050565b6000836bffffffffffffffffffffffff16836bffffffffffffffffffffffff1611158290611f48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f3f9190612ca6565b60405180910390fd5b508284611f559190613d54565b90509392505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603611fcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc490613e2c565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361203c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161203390613ee4565b60405180910390fd5b6120b6600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046bffffffffffffffffffffffff16826040518060600160405280603f8152602001614101603f9139611ee4565b600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555061219d600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046bffffffffffffffffffffffff16826040518060600160405280603981526020016141db6039913961234a565b600460008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516122679190613f3f565b60405180910390a3612338600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600560008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16836123c9565b505050565b6000804690508091505090565b60008083856123599190613f5a565b9050846bffffffffffffffffffffffff16816bffffffffffffffffffffffff16101583906123bd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123b49190612ca6565b60405180910390fd5b50809150509392505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415801561241357506000816bffffffffffffffffffffffff16115b156126d157600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614612574576000600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900463ffffffff1690506000808263ffffffff16116124b657600061253b565b600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600184612504919061362a565b63ffffffff1663ffffffff16815260200190815260200160002060000160049054906101000a90046bffffffffffffffffffffffff165b90506000612562828560405180606001604052806031815260200161402e60319139611ee4565b905061257086848484612896565b5050505b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146126d0576000600760008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900463ffffffff1690506000808263ffffffff1611612612576000612697565b600660008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600184612660919061362a565b63ffffffff1663ffffffff16815260200190815260200160002060000160049054906101000a90046bffffffffffffffffffffffff165b905060006126be82856040518060600160405280603081526020016142146030913961234a565b90506126cc85848484612896565b5050505b5b505050565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506000600460008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a90046bffffffffffffffffffffffff16905082600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f60405160405180910390a46128908284836123c9565b50505050565b60006128ba436040518060600160405280603d815260200161416e603d9139612bc0565b905060008463ffffffff1611801561295857508063ffffffff16600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000600187612922919061362a565b63ffffffff1663ffffffff16815260200190815260200160002060000160009054906101000a900463ffffffff1663ffffffff16145b156129fc5781600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006001876129ac919061362a565b63ffffffff1663ffffffff16815260200190815260200160002060000160046101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550612b4d565b60405180604001604052808263ffffffff168152602001836bffffffffffffffffffffffff16815250600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008663ffffffff1663ffffffff16815260200190815260200160002060008201518160000160006101000a81548163ffffffff021916908363ffffffff16021790555060208201518160000160046101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550905050600184612aef9190613f9a565b600760008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548163ffffffff021916908363ffffffff1602179055505b8473ffffffffffffffffffffffffffffffffffffffff167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724846bffffffffffffffffffffffff16846bffffffffffffffffffffffff16604051612bb1929190613fd2565b60405180910390a25050505050565b600064010000000083108290612c0c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c039190612ca6565b60405180910390fd5b5082905092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015612c50578082015181840152602081019050612c35565b60008484015250505050565b6000601f19601f8301169050919050565b6000612c7882612c16565b612c828185612c21565b9350612c92818560208601612c32565b612c9b81612c5c565b840191505092915050565b60006020820190508181036000830152612cc08184612c6d565b905092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612cf382612cc8565b9050919050565b612d0381612ce8565b82525050565b6000602082019050612d1e6000830184612cfa565b92915050565b600080fd5b612d3281612ce8565b8114612d3d57600080fd5b50565b600081359050612d4f81612d29565b92915050565b6000819050919050565b612d6881612d55565b8114612d7357600080fd5b50565b600081359050612d8581612d5f565b92915050565b60008060408385031215612da257612da1612d24565b5b6000612db085828601612d40565b9250506020612dc185828601612d76565b9150509250929050565b60008115159050919050565b612de081612dcb565b82525050565b6000602082019050612dfb6000830184612dd7565b92915050565b612e0a81612d55565b82525050565b6000602082019050612e256000830184612e01565b92915050565b6000819050919050565b612e3e81612e2b565b82525050565b6000602082019050612e596000830184612e35565b92915050565b600080600060608486031215612e7857612e77612d24565b5b6000612e8686828701612d40565b9350506020612e9786828701612d40565b9250506040612ea886828701612d76565b9150509250925092565b600060ff82169050919050565b612ec881612eb2565b82525050565b6000602082019050612ee36000830184612ebf565b92915050565b600060208284031215612eff57612efe612d24565b5b6000612f0d84828501612d40565b91505092915050565b600063ffffffff82169050919050565b612f2f81612f16565b82525050565b6000602082019050612f4a6000830184612f26565b92915050565b60006bffffffffffffffffffffffff82169050919050565b612f7181612f50565b82525050565b6000602082019050612f8c6000830184612f68565b92915050565b612f9b81612eb2565b8114612fa657600080fd5b50565b600081359050612fb881612f92565b92915050565b612fc781612e2b565b8114612fd257600080fd5b50565b600081359050612fe481612fbe565b92915050565b60008060008060008060c0878903121561300757613006612d24565b5b600061301589828a01612d40565b965050602061302689828a01612d76565b955050604061303789828a01612d76565b945050606061304889828a01612fa9565b935050608061305989828a01612fd5565b92505060a061306a89828a01612fd5565b9150509295509295509295565b600080600080600080600060e0888a03121561309657613095612d24565b5b60006130a48a828b01612d40565b97505060206130b58a828b01612d40565b96505060406130c68a828b01612d76565b95505060606130d78a828b01612d76565b94505060806130e88a828b01612fa9565b93505060a06130f98a828b01612fd5565b92505060c061310a8a828b01612fd5565b91505092959891949750929550565b600080604083850312156131305761312f612d24565b5b600061313e85828601612d40565b925050602061314f85828601612d40565b9150509250929050565b61316281612f16565b811461316d57600080fd5b50565b60008135905061317f81613159565b92915050565b6000806040838503121561319c5761319b612d24565b5b60006131aa85828601612d40565b92505060206131bb85828601613170565b9150509250929050565b60006040820190506131da6000830185612f26565b6131e76020830184612f68565b9392505050565b60006080820190506132036000830187612e35565b6132106020830186612e35565b61321d6040830185612e01565b61322a6060830184612cfa565b95945050505050565b7f426c75656265727279546f6b656e2e6d696e743a206f6e6c7920746865206d6960008201527f6e7465722063616e206d696e7400000000000000000000000000000000000000602082015250565b600061328f602d83612c21565b915061329a82613233565b604082019050919050565b600060208201905081810360008301526132be81613282565b9050919050565b7f426c75656265727279546f6b656e2e6d696e743a206d696e74696e67206e6f7460008201527f20616c6c6f776564207965740000000000000000000000000000000000000000602082015250565b6000613321602c83612c21565b915061332c826132c5565b604082019050919050565b6000602082019050818103600083015261335081613314565b9050919050565b7f426c75656265727279546f6b656e2e6d696e743a2063616e6e6f74207472616e60008201527f7366657220746f20746865207a65726f20616464726573730000000000000000602082015250565b60006133b3603883612c21565b91506133be82613357565b604082019050919050565b600060208201905081810360008301526133e2816133a6565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061342382612d55565b915061342e83612d55565b9250828201905080821115613446576134456133e9565b5b92915050565b600061345782612d55565b915061346283612d55565b9250817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561349b5761349a6133e9565b5b828202905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006134e082612d55565b91506134eb83612d55565b9250826134fb576134fa6134a6565b5b828204905092915050565b7f426c75656265727279546f6b656e2e6d696e743a206578636565646564206d6960008201527f6e74206361700000000000000000000000000000000000000000000000000000602082015250565b6000613562602683612c21565b915061356d82613506565b604082019050919050565b6000602082019050818103600083015261359181613555565b9050919050565b7f426c75656265727279546f6b656e2e6765745072696f72566f7465733a206e6f60008201527f74207965742064657465726d696e656400000000000000000000000000000000602082015250565b60006135f4603083612c21565b91506135ff82613598565b604082019050919050565b60006020820190508181036000830152613623816135e7565b9050919050565b600061363582612f16565b915061364083612f16565b9250828203905063ffffffff81111561365c5761365b6133e9565b5b92915050565b600061366d82612f16565b915061367883612f16565b925082613688576136876134a6565b5b828204905092915050565b60006080820190506136a86000830187612e35565b6136b56020830186612cfa565b6136c26040830185612e01565b6136cf6060830184612e01565b95945050505050565b600081905092915050565b7f1901000000000000000000000000000000000000000000000000000000000000600082015250565b60006137196002836136d8565b9150613724826136e3565b600282019050919050565b6000819050919050565b61374a61374582612e2b565b61372f565b82525050565b600061375b8261370c565b91506137678285613739565b6020820191506137778284613739565b6020820191508190509392505050565b600060808201905061379c6000830187612e35565b6137a96020830186612ebf565b6137b66040830185612e35565b6137c36060830184612e35565b95945050505050565b7f426c75656265727279546f6b656e2e64656c656761746542795369673a20696e60008201527f76616c6964207369676e61747572650000000000000000000000000000000000602082015250565b6000613828602f83612c21565b9150613833826137cc565b604082019050919050565b600060208201905081810360008301526138578161381b565b9050919050565b600061386982612d55565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361389b5761389a6133e9565b5b600182019050919050565b7f426c75656265727279546f6b656e2e64656c656761746542795369673a20696e60008201527f76616c6964206e6f6e6365000000000000000000000000000000000000000000602082015250565b6000613902602b83612c21565b915061390d826138a6565b604082019050919050565b60006020820190508181036000830152613931816138f5565b9050919050565b7f426c75656265727279546f6b656e2e64656c656761746542795369673a20736960008201527f676e617475726520657870697265640000000000000000000000000000000000602082015250565b6000613994602f83612c21565b915061399f82613938565b604082019050919050565b600060208201905081810360008301526139c381613987565b9050919050565b600060c0820190506139df6000830189612e35565b6139ec6020830188612cfa565b6139f96040830187612cfa565b613a066060830186612e01565b613a136080830185612e01565b613a2060a0830184612e01565b979650505050505050565b7f426c75656265727279546f6b656e2e7065726d69743a20696e76616c6964207360008201527f69676e6174757265000000000000000000000000000000000000000000000000602082015250565b6000613a87602883612c21565b9150613a9282613a2b565b604082019050919050565b60006020820190508181036000830152613ab681613a7a565b9050919050565b7f426c75656265727279546f6b656e2e7065726d69743a20756e617574686f726960008201527f7a65640000000000000000000000000000000000000000000000000000000000602082015250565b6000613b19602383612c21565b9150613b2482613abd565b604082019050919050565b60006020820190508181036000830152613b4881613b0c565b9050919050565b7f426c75656265727279546f6b656e2e7065726d69743a207369676e617475726560008201527f2065787069726564000000000000000000000000000000000000000000000000602082015250565b6000613bab602883612c21565b9150613bb682613b4f565b604082019050919050565b60006020820190508181036000830152613bda81613b9e565b9050919050565b7f426c75656265727279546f6b656e2e7365744d696e7465723a206f6e6c79207460008201527f6865206d696e7465722063616e206368616e676520746865206d696e7465722060208201527f6164647265737300000000000000000000000000000000000000000000000000604082015250565b6000613c63604783612c21565b9150613c6e82613be1565b606082019050919050565b60006020820190508181036000830152613c9281613c56565b9050919050565b7f426c75656265727279546f6b656e2e7365744d696e7465723a2063616e6e6f7460008201527f20757365207a65726f2061646472657373000000000000000000000000000000602082015250565b6000613cf5603183612c21565b9150613d0082613c99565b604082019050919050565b60006020820190508181036000830152613d2481613ce8565b9050919050565b6000604082019050613d406000830185612cfa565b613d4d6020830184612cfa565b9392505050565b6000613d5f82612f50565b9150613d6a83612f50565b925082820390506bffffffffffffffffffffffff811115613d8e57613d8d6133e9565b5b92915050565b7f426c75656265727279546f6b656e2e5f7472616e73666572546f6b656e733a2060008201527f63616e6e6f74207472616e736665722066726f6d20746865207a65726f20616460208201527f6472657373000000000000000000000000000000000000000000000000000000604082015250565b6000613e16604583612c21565b9150613e2182613d94565b606082019050919050565b60006020820190508181036000830152613e4581613e09565b9050919050565b7f426c75656265727279546f6b656e2e5f7472616e73666572546f6b656e733a2060008201527f63616e6e6f74207472616e7366657220746f20746865207a65726f206164647260208201527f6573730000000000000000000000000000000000000000000000000000000000604082015250565b6000613ece604383612c21565b9150613ed982613e4c565b606082019050919050565b60006020820190508181036000830152613efd81613ec1565b9050919050565b6000819050919050565b6000613f29613f24613f1f84612f50565b613f04565b612d55565b9050919050565b613f3981613f0e565b82525050565b6000602082019050613f546000830184613f30565b92915050565b6000613f6582612f50565b9150613f7083612f50565b925082820190506bffffffffffffffffffffffff811115613f9457613f936133e9565b5b92915050565b6000613fa582612f16565b9150613fb083612f16565b9250828201905063ffffffff811115613fcc57613fcb6133e9565b5b92915050565b6000604082019050613fe76000830185612e01565b613ff46020830184612e01565b939250505056fe426c75656265727279546f6b656e2e6d696e743a2064657374696e6174696f6e2062616c616e6365206f766572666c6f7773426c75656265727279546f6b656e2e5f6d6f7665566f7465733a20766f746520616d6f756e7420756e646572666c6f7773426c75656265727279546f6b656e2e7472616e736665723a20616d6f756e7420657863656564732039362062697473426c75656265727279546f6b656e2e7065726d69743a20616d6f756e7420657863656564732039362062697473426c75656265727279546f6b656e2e7472616e7366657246726f6d3a207472616e7366657220616d6f756e742065786365656473207370656e64657220616c6c6f77616e6365426c75656265727279546f6b656e2e5f7472616e73666572546f6b656e733a207472616e7366657220616d6f756e7420657863656564732062616c616e6365426c75656265727279546f6b656e2e617070726f76653a20616d6f756e7420657863656564732039362062697473426c75656265727279546f6b656e2e5f7772697465436865636b706f696e743a20626c6f636b206e756d62657220657863656564732033322062697473426c75656265727279546f6b656e2e6d696e743a20746f74616c537570706c7920657863656564732039362062697473426c75656265727279546f6b656e2e5f7472616e73666572546f6b656e733a207472616e7366657220616d6f756e74206f766572666c6f7773426c75656265727279546f6b656e2e5f6d6f7665566f7465733a20766f746520616d6f756e74206f766572666c6f7773426c75656265727279546f6b656e2e6d696e743a20616d6f756e7420657863656564732039362062697473a264697066735822122025d57fbf1b13b860b9366aee6ba5c4a70159b790059e7605e5a7bb2d39a1483364736f6c63430008100033
Verified Source Code Full Match
Compiler: v0.8.16+commit.07a7930e
EVM: london
Optimization: No
BlueberryToken.sol 677 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./IBlueberryToken.sol";
contract BlueberryToken is IBlueberryToken {
using SafeERC20 for IERC20;
// EIP-20 token name for this token
string public constant override name = "Blueberry";
// EIP-20 token symbol for this token
string public constant override symbol = "BLB";
// EIP-20 token decimals for this token
uint8 public constant override decimals = 18;
// Total number of tokens in circulation
// Initially capped at 1 billion BLB
// On top of it 2% extra (inflactionary) tokens can be minted in 1 year intervals
uint256 public override totalSupply = 1_000_000_000e18;
// Address which may mint inflationary tokens
address public override minter;
// The timestamp after which inflationary minting may occur
uint256 public override mintingAllowedAfter;
// Minimum time between inflationary mints
uint32 public constant override minimumTimeBetweenMints = 1 days * 365;
// Cap on the percentage of totalSupply that can be minted at each inflationary mint
uint8 public constant override mintCap = 2;
// constant that represents 100%
uint256 constant PERCENT = 100;
address constant NULL_ADDRESS = address(0);
// Allowance amounts on behalf of others
mapping(address => mapping(address => uint96)) internal allowances;
// Official record of token balances for each account
mapping(address => uint96) internal balances;
// A record of each accounts delegate
mapping(address => address) public override delegates;
// A checkpoint for marking number of votes from a given block
struct Checkpoint {
uint32 fromBlock;
uint96 votes;
}
// A record of votes checkpoints for each account, by index
mapping(address => mapping(uint32 => Checkpoint))
public
override checkpoints;
// The number of checkpoints for each account
mapping(address => uint32) public override numCheckpoints;
// The EIP-712 typehash for the contract's domain
bytes32 public constant override DOMAIN_TYPEHASH =
keccak256(
"EIP712Domain(string name,uint256 chainId,address verifyingContract)"
);
// The EIP-712 typehash for the delegation struct used by the contract
bytes32 public constant override DELEGATION_TYPEHASH =
keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
// The EIP-712 typehash for the permit struct used by the contract
bytes32 public constant override PERMIT_TYPEHASH =
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
);
// A record of states for signing / validating signatures
mapping(address => uint256) public override nonces;
/**
* @notice Construct a new Blueberry token
* @param account The initial account to grant 1 billion tokens
* @param minter_ The account with minting ability
* @param mintingAllowedAfter_ The timestamp after which inflationary minting may occur
*/
constructor(
address account,
address minter_,
uint256 mintingAllowedAfter_
) {
require(
mintingAllowedAfter_ >= block.timestamp,
"BlueberryToken.constructor: minting can only begin after deployment"
);
require(
account != NULL_ADDRESS && minter_ != NULL_ADDRESS,
"BlueberryToken.constructor: cannot init with zero addresses"
);
balances[account] = uint96(totalSupply);
minter = minter_;
mintingAllowedAfter = mintingAllowedAfter_;
emit Transfer(NULL_ADDRESS, account, totalSupply);
emit MinterChanged(NULL_ADDRESS, minter);
}
/**
* @notice Change the minter address
* @param minter_ The address of the new minter
*/
function setMinter(address minter_) external override {
require(
msg.sender == minter,
"BlueberryToken.setMinter: only the minter can change the minter address"
);
require(
minter_ != NULL_ADDRESS,
"BlueberryToken.setMinter: cannot use zero address"
);
emit MinterChanged(minter, minter_);
minter = minter_;
}
/**
* @notice Mint new tokens
* @param dst The address of the destination account
* @param amount The number of tokens to be minted
*/
function mint(address dst, uint256 amount) external override {
require(
msg.sender == minter,
"BlueberryToken.mint: only the minter can mint"
);
require(
block.timestamp >= mintingAllowedAfter,
"BlueberryToken.mint: minting not allowed yet"
);
require(
dst != NULL_ADDRESS,
"BlueberryToken.mint: cannot transfer to the zero address"
);
// record the mint
mintingAllowedAfter = block.timestamp + minimumTimeBetweenMints;
// mint the amount
uint96 amount96 = safe96(
amount,
"BlueberryToken.mint: amount exceeds 96 bits"
);
require(
amount <= (totalSupply * mintCap) / PERCENT,
"BlueberryToken.mint: exceeded mint cap"
);
totalSupply = uint256(
safe96(
totalSupply + amount,
"BlueberryToken.mint: totalSupply exceeds 96 bits"
)
);
// transfer the amount to the recipient
balances[dst] = add96(
balances[dst],
amount96,
"BlueberryToken.mint: destination balance overflows"
);
emit Transfer(NULL_ADDRESS, dst, amount);
// move delegates
_moveDelegates(NULL_ADDRESS, delegates[dst], amount96);
}
/**
* @notice Get the number of tokens `spender` is approved to spend on behalf of `account`
* @param _owner The address of the account holding the funds
* @param _spender The address of the account spending the funds
* @return The number of tokens approved
*/
function allowance(address _owner, address _spender)
external
view
override
returns (uint256)
{
return uint256(allowances[_owner][_spender]);
}
/**
* @notice Approve `spender` to transfer up to `amount` from `src`
* @dev This will overwrite the approval amount for `spender`
* and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
* @param _spender The address of the account which may transfer tokens
* @param _value The number of tokens that are approved (2^256-1 means infinite)
* @return Whether or not the approval succeeded
*/
function approve(address _spender, uint256 _value)
external
override
returns (bool)
{
uint96 amount;
if (_value == type(uint256).max) {
amount = type(uint96).max;
} else {
amount = safe96(
_value,
"BlueberryToken.approve: amount exceeds 96 bits"
);
}
allowances[msg.sender][_spender] = amount;
emit Approval(msg.sender, _spender, uint256(amount));
return true;
}
/**
* @notice Returns the domain separator used in the encoding of the signature for `permit`, as defined by {EIP712}.
* @return domain separator
*/
function DOMAIN_SEPARATOR() public view override returns (bytes32) {
return
keccak256(
abi.encode(
DOMAIN_TYPEHASH,
keccak256(bytes(name)),
getChainId(),
address(this)
)
);
}
/**
* @notice Triggers an approval from owner to spends
* @param owner The address to approve from
* @param spender The address to be approved
* @param rawAmount The number of tokens that are approved (2^256-1 means infinite)
* @param deadline The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function permit(
address owner,
address spender,
uint256 rawAmount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external override {
uint96 amount;
if (rawAmount == type(uint256).max) {
amount = type(uint96).max;
} else {
amount = safe96(
rawAmount,
"BlueberryToken.permit: amount exceeds 96 bits"
);
}
bytes32 structHash = keccak256(
abi.encode(
PERMIT_TYPEHASH,
owner,
spender,
rawAmount,
nonces[owner]++,
deadline
)
);
bytes32 digest = keccak256(
abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), structHash)
);
address signatory = ecrecover(digest, v, r, s);
require(
signatory != NULL_ADDRESS,
"BlueberryToken.permit: invalid signature"
);
require(signatory == owner, "BlueberryToken.permit: unauthorized");
require(
block.timestamp <= deadline,
"BlueberryToken.permit: signature expired"
);
allowances[owner][spender] = amount;
emit Approval(owner, spender, uint256(amount));
}
/**
* @notice Get the number of tokens held by the `account`
* @param _owner The address of the account to get the balance of
* @return The number of tokens held
*/
function balanceOf(address _owner)
external
view
override
returns (uint256)
{
return uint256(balances[_owner]);
}
/**
* @notice Transfer `amount` tokens from `msg.sender` to `dst`
* @param _to The address of the destination account
* @param _value The number of tokens to transfer
* @return Whether or not the transfer succeeded
*/
function transfer(address _to, uint256 _value)
external
override
returns (bool)
{
uint96 amount = safe96(
_value,
"BlueberryToken.transfer: amount exceeds 96 bits"
);
_transferTokens(msg.sender, _to, amount);
return true;
}
/**
* @notice Transfer `amount` tokens from `src` to `dst`
* @param _from The address of the source account
* @param _to The address of the destination account
* @param _value The number of tokens to transfer
* @return Whether or not the transfer succeeded
*/
function transferFrom(
address _from,
address _to,
uint256 _value
) external override returns (bool) {
address spender = msg.sender;
uint96 spenderAllowance = allowances[_from][spender];
uint96 amount96 = safe96(
_value,
"BlueberryToken.approve: amount exceeds 96 bits"
);
if (spender != _from && spenderAllowance != type(uint96).max) {
uint96 newAllowance = sub96(
spenderAllowance,
amount96,
"BlueberryToken.transferFrom: transfer amount exceeds spender allowance"
);
allowances[_from][spender] = newAllowance;
emit Approval(_from, spender, uint256(newAllowance));
}
_transferTokens(_from, _to, amount96);
return true;
}
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/
function delegate(address delegatee) public override {
return _delegate(msg.sender, delegatee);
}
/**
* @notice Delegates votes from signatory to `delegatee`
* @param delegatee The address to delegate votes to
* @param nonce The contract state required to match the signature
* @param expiry The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function delegateBySig(
address delegatee,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) public override {
bytes32 structHash = keccak256(
abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry)
);
bytes32 digest = keccak256(
abi.encodePacked("\x19\x01", DOMAIN_SEPARATOR(), structHash)
);
address signatory = ecrecover(digest, v, r, s);
require(
signatory != NULL_ADDRESS,
"BlueberryToken.delegateBySig: invalid signature"
);
require(
nonce == nonces[signatory]++,
"BlueberryToken.delegateBySig: invalid nonce"
);
require(
block.timestamp <= expiry,
"BlueberryToken.delegateBySig: signature expired"
);
return _delegate(signatory, delegatee);
}
/**
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @return The number of current votes for `account`
*/
function getCurrentVotes(address account)
external
view
override
returns (uint96)
{
uint32 nCheckpoints = numCheckpoints[account];
return
nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
}
/**
* @notice Determine the prior number of votes for an account as of a block number
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
* @param account The address of the account to check
* @param blockNumber The block number to get the vote balance at
* @return The number of votes the account had as of the given block
*/
function getPriorVotes(address account, uint256 blockNumber)
public
view
override
returns (uint96)
{
require(
blockNumber < block.number,
"BlueberryToken.getPriorVotes: not yet determined"
);
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
// First check most recent balance
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
return checkpoints[account][nCheckpoints - 1].votes;
}
// Next check implicit zero balance
if (checkpoints[account][0].fromBlock > blockNumber) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
Checkpoint memory cp = checkpoints[account][center];
if (cp.fromBlock == blockNumber) {
return cp.votes;
} else if (cp.fromBlock < blockNumber) {
lower = center;
} else {
upper = center - 1;
}
}
return checkpoints[account][lower].votes;
}
/**
* @notice Delegate votes from `delegator` to `delegatee`
* @param delegator The address of the delegator
* @param delegatee The address to delegate votes to
*/
function _delegate(address delegator, address delegatee) internal {
address currentDelegate = delegates[delegator];
uint96 delegatorBalance = balances[delegator];
delegates[delegator] = delegatee;
emit DelegateChanged(delegator, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, delegatorBalance);
}
/**
* @notice Transfer `amount` tokens from `src` to `dst`
* @param src The address of the source account
* @param dst The address of the destination account
* @param amount The number of tokens to transfer
*/
function _transferTokens(
address src,
address dst,
uint96 amount
) internal {
require(
src != NULL_ADDRESS,
"BlueberryToken._transferTokens: cannot transfer from the zero address"
);
require(
dst != NULL_ADDRESS,
"BlueberryToken._transferTokens: cannot transfer to the zero address"
);
balances[src] = sub96(
balances[src],
amount,
"BlueberryToken._transferTokens: transfer amount exceeds balance"
);
balances[dst] = add96(
balances[dst],
amount,
"BlueberryToken._transferTokens: transfer amount overflows"
);
emit Transfer(src, dst, amount);
_moveDelegates(delegates[src], delegates[dst], amount);
}
/**
* @notice Move delegate votes from `delegator` to `delegatee`
* @param srcRep The address of the delegator
* @param dstRep The address to delegate votes to
* @param amount The number of tokens to delegate
*/
function _moveDelegates(
address srcRep,
address dstRep,
uint96 amount
) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != NULL_ADDRESS) {
uint32 srcRepNum = numCheckpoints[srcRep];
uint96 srcRepOld = srcRepNum > 0
? checkpoints[srcRep][srcRepNum - 1].votes
: 0;
uint96 srcRepNew = sub96(
srcRepOld,
amount,
"BlueberryToken._moveVotes: vote amount underflows"
);
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
if (dstRep != NULL_ADDRESS) {
uint32 dstRepNum = numCheckpoints[dstRep];
uint96 dstRepOld = dstRepNum > 0
? checkpoints[dstRep][dstRepNum - 1].votes
: 0;
uint96 dstRepNew = add96(
dstRepOld,
amount,
"BlueberryToken._moveVotes: vote amount overflows"
);
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
/**
* @notice Create new votes checkpoint for a `delegatee`
* @param delegatee The address of the delegatee
* @param nCheckpoints Current number of checkpoints for the `delegatee`
* @param oldVotes Old number of votes
* @param newVotes New number of votes
*/
function _writeCheckpoint(
address delegatee,
uint32 nCheckpoints,
uint96 oldVotes,
uint96 newVotes
) internal {
uint32 blockNumber = safe32(
block.number,
"BlueberryToken._writeCheckpoint: block number exceeds 32 bits"
);
if (
nCheckpoints > 0 &&
checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber
) {
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
} else {
checkpoints[delegatee][nCheckpoints] = Checkpoint(
blockNumber,
newVotes
);
numCheckpoints[delegatee] = nCheckpoints + 1;
}
emit DelegateVotesChanged(
delegatee,
uint256(oldVotes),
uint256(newVotes)
);
}
/**
* @notice safe conversion to uint32
* @param n number to convert
* @param errorMessage error raised during the conversion
* @return converted unit32 number
*/
function safe32(uint256 n, string memory errorMessage)
internal
pure
returns (uint32)
{
require(n < 2**32, errorMessage);
return uint32(n);
}
/**
* @notice safe conversion to uint96
* @param n number to convert
* @param errorMessage error raised during the conversion
* @return converted unit96 number
*/
function safe96(uint256 n, string memory errorMessage)
internal
pure
returns (uint96)
{
require(n < 2**96, errorMessage);
return uint96(n);
}
/**
* @notice safe addition for uint96
* @param a number to add
* @param b number to add
* @param errorMessage error raised during the conversion
* @return the result of the addition
*/
function add96(
uint96 a,
uint96 b,
string memory errorMessage
) internal pure returns (uint96) {
uint96 c = a + b;
require(c >= a, errorMessage);
return c;
}
/**
* @notice safe subtraction for uint96
* @param a initial number
* @param b number to subtract
* @param errorMessage error raised during the conversion
* @return the result of the subtraction
*/
function sub96(
uint96 a,
uint96 b,
string memory errorMessage
) internal pure returns (uint96) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @notice returns the chain ID
* @return chain ID
*/
function getChainId() internal view returns (uint256) {
uint256 chainId;
assembly {
chainId := chainid()
}
return chainId;
}
}
IBlueberryToken.sol 122 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
interface IBlueberryToken is IERC20, IERC20Permit {
// EIP-20 token name for this token
function name() external view returns (string memory);
// EIP-20 token symbol for this token
function symbol() external view returns (string memory);
// EIP-20 token decimals for this token
function decimals() external view returns (uint8);
// Address which may mint inflationary tokens
function minter() external view returns (address);
// The timestamp after which inflationary minting may occur
function mintingAllowedAfter() external view returns (uint256);
// Minimum time between inflationary mints
function minimumTimeBetweenMints() external view returns (uint32);
// Cap on the percentage of totalSupply that can be minted at each inflationary mint
function mintCap() external view returns (uint8);
// A record of each accounts delegate
function delegates(address) external view returns (address);
// A record of votes checkpoints for each account, by index
function checkpoints(address, uint32)
external
view
returns (uint32, uint96);
// The number of checkpoints for each account
function numCheckpoints(address) external view returns (uint32);
// The EIP-712 typehash for the contract's domain
function DOMAIN_TYPEHASH() external view returns (bytes32);
// The EIP-712 typehash for the delegation struct used by the contract
function DELEGATION_TYPEHASH() external view returns (bytes32);
// The EIP-712 typehash for the permit struct used by the contract
function PERMIT_TYPEHASH() external view returns (bytes32);
// An event thats emitted when the minter address is changed
event MinterChanged(address minter, address newMinter);
// An event thats emitted when an account changes its delegate
event DelegateChanged(
address indexed delegator,
address indexed fromDelegate,
address indexed toDelegate
);
// An event thats emitted when a delegate account's vote balance changes
event DelegateVotesChanged(
address indexed delegate,
uint256 previousBalance,
uint256 newBalance
);
/**
* @notice Change the minter address
* @param minter_ The address of the new minter
*/
function setMinter(address minter_) external;
/**
* @notice Mint new tokens
* @param dst The address of the destination account
* @param rawAmount The number of tokens to be minted
*/
function mint(address dst, uint256 rawAmount) external;
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/
function delegate(address delegatee) external;
/**
* @notice Delegates votes from signatory to `delegatee`
* @param delegatee The address to delegate votes to
* @param nonce The contract state required to match the signature
* @param expiry The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function delegateBySig(
address delegatee,
uint256 nonce,
uint256 expiry,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @return The number of current votes for `account`
*/
function getCurrentVotes(address account) external view returns (uint96);
/**
* @notice Determine the prior number of votes for an account as of a block number
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
* @param account The address of the account to check
* @param blockNumber The block number to get the vote balance at
* @return The number of votes the account had as of the given block
*/
function getPriorVotes(address account, uint256 blockNumber)
external
view
returns (uint96);
}
SafeERC20.sol 116 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
draft-IERC20Permit.sol 60 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
IERC20.sol 82 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
Address.sol 244 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
Read Contract
DELEGATION_TYPEHASH 0xe7a324dc → bytes32
DOMAIN_SEPARATOR 0x3644e515 → bytes32
DOMAIN_TYPEHASH 0x20606b70 → bytes32
PERMIT_TYPEHASH 0x30adf81f → bytes32
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
checkpoints 0xf1127ed8 → uint32, uint96
decimals 0x313ce567 → uint8
delegates 0x587cde1e → address
getCurrentVotes 0xb4b5ea57 → uint96
getPriorVotes 0x782d6fe1 → uint96
minimumTimeBetweenMints 0x5c11d62f → uint32
mintCap 0x76c71ca1 → uint8
minter 0x07546172 → address
mintingAllowedAfter 0x30b36cef → uint256
name 0x06fdde03 → string
nonces 0x7ecebe00 → uint256
numCheckpoints 0x6fcfff45 → uint32
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
Write Contract 8 functions
These functions modify contract state and require a wallet transaction to execute.
approve 0x095ea7b3
address _spender
uint256 _value
returns: bool
delegate 0x5c19a95c
address delegatee
delegateBySig 0xc3cda520
address delegatee
uint256 nonce
uint256 expiry
uint8 v
bytes32 r
bytes32 s
mint 0x40c10f19
address dst
uint256 amount
permit 0xd505accf
address owner
address spender
uint256 rawAmount
uint256 deadline
uint8 v
bytes32 r
bytes32 s
setMinter 0xfca3b5aa
address minter_
transfer 0xa9059cbb
address _to
uint256 _value
returns: bool
transferFrom 0x23b872dd
address _from
address _to
uint256 _value
returns: bool
Recent Transactions
No transactions found for this address