Address Contract Partially Verified
Address
0xfF20817765cB7f73d4bde2e66e067E58D11095C2
Balance
0 ETH
Nonce
1
Code Size
13920 bytes
Creator
0x8EbE64E6...7C87 at tx 0xe188a56a...92b5c1
Last Active
Indexed Transactions
1 (24,584,032 → 24,584,032)
Gas Used (indexed)
69,786
Contract Bytecode
13920 bytes
0x608060405234801561001057600080fd5b50600436106102695760003560e01c8063740ab8f411610151578063a2c1cae2116100c3578063b9d7b47111610087578063b9d7b4711461090f578063c2f89a5114610917578063dc73e49c14610949578063dd62ed3e14610951578063e30834e01461097f578063fad8b32a146109b557610269565b8063a2c1cae21461084d578063a457c2d714610855578063a9059cbb14610881578063aeb72e70146108ad578063b6363cf2146108e157610269565b80638da5cb5b116101155780638da5cb5b146107cb578063900ff16d146107d3578063959b8c3f146107fa57806395d89b4114610820578063a0cf6b8414610828578063a26734dc1461083057610269565b8063740ab8f41461072057806375deca02146107465780637e3a262d14610780578063814435af1461078857806387f4427e146107a557610269565b80632036a94d116101ea57806339509351116101ae57806339509351146106165780635481eed314610642578063556f0dc71461066657806369598efe1461066e5780636d77cad6146106c657806370a08231146106fa57610269565b80632036a94d1461048357806323b872dd1461056a578063249cb3fa146105a057806330e82803146105cc578063313ce567146105f857610269565b806314d1e62f1161023157806314d1e62f146103a5578063168ecec5146103d757806317ec83ca1461040357806318160ddd146104495780631ff6442e1461045157610269565b806303438dd01461026e57806306fdde0314610296578063095ea7b3146103135780630e0e923b14610353578063103ef9e114610379575b600080fd5b6102946004803603602081101561028457600080fd5b50356001600160a01b03166109db565b005b61029e610c41565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102d85781810151838201526020016102c0565b50505050905090810190601f1680156103055780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61033f6004803603604081101561032957600080fd5b506001600160a01b038135169060200135610cd7565b604080519115158252519081900360200190f35b61033f6004803603602081101561036957600080fd5b50356001600160a01b0316610cef565b6102946004803603604081101561038f57600080fd5b50803590602001356001600160a01b0316610d0c565b61033f600480360360608110156103bb57600080fd5b508035906001600160a01b036020820135169060400135610de3565b610294600480360360408110156103ed57600080fd5b50803590602001356001600160a01b0316610dfc565b6104376004803603606081101561041957600080fd5b508035906001600160a01b0360208201358116916040013516610ed0565b60408051918252519081900360200190f35b610437610f00565b61033f6004803603606081101561046757600080fd5b508035906001600160a01b036020820135169060400135610f06565b610437600480360360c081101561049957600080fd5b8135916001600160a01b03602082013581169260408301359091169160608101359181019060a0810160808201356401000000008111156104d957600080fd5b8201836020820111156104eb57600080fd5b8035906020019184600183028401116401000000008311171561050d57600080fd5b91939092909160208101903564010000000081111561052b57600080fd5b82018360208201111561053d57600080fd5b8035906020019184600183028401116401000000008311171561055f57600080fd5b509092509050610f50565b61033f6004803603606081101561058057600080fd5b506001600160a01b03813581169160208101359091169060400135610fd7565b610437600480360360408110156105b657600080fd5b50803590602001356001600160a01b0316610ff5565b610437600480360360408110156105e257600080fd5b50803590602001356001600160a01b0316611059565b61060061107e565b6040805160ff9092168252519081900360200190f35b61033f6004803603604081101561062c57600080fd5b506001600160a01b038135169060200135611083565b61064a6110e1565b604080516001600160a01b039092168252519081900360200190f35b6104376110f0565b6106766110f5565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156106b257818101518382015260200161069a565b505050509050019250505060405180910390f35b61033f600480360360608110156106dc57600080fd5b508035906001600160a01b036020820135811691604001351661114c565b6104376004803603602081101561071057600080fd5b50356001600160a01b0316611161565b6106766004803603602081101561073657600080fd5b50356001600160a01b031661117c565b6107636004803603602081101561075c57600080fd5b50356111e8565b604080516001600160e01b03199092168252519081900360200190f35b61043761121c565b61064a6004803603602081101561079e57600080fd5b5035611221565b610294600480360360208110156107bb57600080fd5b50356001600160a01b0316611248565b61064a6112e8565b61033f600480360360208110156107e957600080fd5b50356001600160e01b0319166112f7565b6102946004803603602081101561081057600080fd5b50356001600160a01b0316611316565b61029e6113e1565b61064a611442565b6104376004803603602081101561084657600080fd5b5035611448565b61029461145a565b61033f6004803603604081101561086b57600080fd5b506001600160a01b03813516906020013561150a565b61033f6004803603604081101561089757600080fd5b506001600160a01b038135169060200135611568565b61033f600480360360608110156108c357600080fd5b508035906001600160a01b0360208201358116916040013516611586565b61033f600480360360408110156108f757600080fd5b506001600160a01b03813581169160200135166115ef565b6102946115fb565b61033f6004803603606081101561092d57600080fd5b508035906001600160a01b036020820135169060400135611705565b61064a61174a565b6104376004803603604081101561096757600080fd5b506001600160a01b0381358116916020013516611759565b6102946004803603604081101561099557600080fd5b5080356001600160e01b03191690602001356001600160a01b03166117a3565b610294600480360360208110156109cb57600080fd5b50356001600160a01b0316611a64565b60235460408051636eb1769f60e11b81526001600160a01b0384811660048301523060248301529151600093929092169163dd62ed3e91604480820192602092909190829003018186803b158015610a3257600080fd5b505afa158015610a46573d6000803e3d6000fd5b505050506040513d6020811015610a5c57600080fd5b50519050600481610b005760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b820191906000526020600020905b815481529060010190602001808311610ad457829003601f168201915b50509250505060405180910390fd5b50602354604080516323b872dd60e01b81526001600160a01b03858116600483015261dead602483015260448201859052915191909216916323b872dd9160648083019260209291908290030181600087803b158015610b5f57600080fd5b505af1158015610b73573d6000803e3d6000fd5b505050506040513d6020811015610b8957600080fd5b5051600f90610bf15760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50610bfd338383611cba565b6040805182815290516001600160a01b0384169133917fea368a40e9570069bb8e6511d668293ad2e1f03b0d982431fd223de9f3b70ca69181900360200190a35050565b60128054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ccd5780601f10610ca257610100808354040283529160200191610ccd565b820191906000526020600020905b815481529060010190602001808311610cb057829003601f168201915b5050505050905090565b6000610ce581338585611e7d565b5060015b92915050565b6001600160a01b0316600090815260208052604090205460ff1690565b60076001600160a01b038216331415610d7e5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601e6020908152604080832086845282528083206001600160a01b0386168085529252808320805460ff1916600117905551909185917f3646a897c70797ecc134b0adc32f471b07bf1d6f451133b0384badab531e3fd69190a45050565b6000610df184338585611e7d565b5060015b9392505050565b60076001600160a01b038216331415610e6e5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601e6020908152604080832086845282528083206001600160a01b0386168085529252808320805460ff1916905551909185917f3b287c4f1bab4df949b33bceacef984f544dc5d5479930d00e4ee8c9d8dd96f29190a45050565b6000928352601d602090815260408085206001600160a01b03948516865282528085209290931684525290205490565b60145490565b6000838152601d60209081526040808320338085529083528184206001600160a01b0387168552909252822054610df19186918690610f4b908763ffffffff61201f16565b611e7d565b6000610fca89338a8a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b908190840183828082843760009201919091525061206192505050565b9998505050505050505050565b6000610df13385858560405180602001604052806000815250612508565b60008281526020819052604081205460ff161561105157604051602001808073455243313832305f4143434550545f4d4147494360601b8152506014019050604051602081830303815290604052805190602001209050610ce9565b506000610ce9565b6001600160a01b03166000908152601b60209081526040808320938352929052205490565b601290565b3360008181527f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd4602090815260408083206001600160a01b03871684529091528120549091610ce5918391908690610f4b908763ffffffff61253116565b6011546001600160a01b031690565b600190565b60606016805480602002602001604051908101604052809291908181526020018280548015610ccd57602002820191906000526020600020905b81548152602001906001019080831161112f575050505050905090565b600061115984848461258b565b949350505050565b6001600160a01b031660009081526015602052604090205490565b6001600160a01b0381166000908152601960209081526040918290208054835181840281018401909452808452606093928301828280156111dc57602002820191906000526020600020905b8154815260200190600101908083116111c8575b50505050509050919050565b602181815481106111f557fe5b9060005260206000209060089182820401919006600402915054906101000a900460e01b81565b600081565b601f818154811061122e57fe5b6000918252602090912001546001600160a01b0316905081565b6010546001600160a01b03163314611298576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b604482015290519081900360640190fd5b601180546001600160a01b0319166001600160a01b0383811691909117918290556040519116907fb58bcc286020502f4931905baafed22acc969c092ed724234c73361efc68839090600090a250565b6010546001600160a01b031690565b6001600160e01b03191660009081526022602052604090205460ff1690565b60076001600160a01b0382163314156113885760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601c602090815260408083206001600160a01b0386168085529252808320805460ff191660011790555190917ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f991a350565b60138054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610ccd5780601f10610ca257610100808354040283529160200191610ccd565b61dead81565b60186020526000908152604090205481565b6011546001600160a01b031633146114aa576040805162461bcd60e51b815260206004820152600e60248201526d24b73b30b634b21039b2b73232b960911b604482015290519081900360640190fd5b60108054601180546001600160a01b03198084166001600160a01b038381169190911795869055911690915560405191811692169082907f343765429aea5a34b3ff6a3785a98a5abb2597aca87bfbb58632c173d585373a90600090a350565b3360008181527f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd4602090815260408083206001600160a01b03871684529091528120549091610ce5918391908690610f4b908763ffffffff61201f16565b6000610ce53333858560405180602001604052806000815250612508565b6001600160a01b038116600090815260208052604081205460ff16801561115957506115b283836125e0565b806111595750506001600160a01b039081166000908152601e60209081526040808320958352948152848220939092168152919052205460ff1690565b6000610df583836125e0565b336000908152602080526040902054600b9060ff16156116745760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50601f805460018181019092557fa03837a25210ee280c2113ff4b77ca23440b19d4866cca721c801278fd08d8070180546001600160a01b0319163390811790915560008181526020808052604091829020805460ff19169094179093558051918252517f2d9629b61129967906b4b31b246507fe09b2b62e2c963a3b9e4d1aff6d4af75b929181900390910190a1565b6000838152601d60209081526040808320338085529083528184206001600160a01b0387168552909252822054610df19186918690610f4b908763ffffffff61253116565b6023546001600160a01b031681565b6001600160a01b0391821660009081527f0a51588b1664495f089dd83d2d26f247920f94a57a4a09f20cf068efc8f82bd46020908152604080832093909416825291909152205490565b6117ab6112e8565b6001600160a01b0316336001600160a01b0316146005906118255760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506001600160e01b03198216600090815260226020526040902054600d9060ff16156118aa5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50600e6001600160e01b0319831661191b5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b5060606119278361262d565b90506119338183611b2c565b6021805460018082019092557f3a6357012c1a3ae0a17d304c9920310382d968ebcc4b1771f41c6b304205b5706008820401805463ffffffff60079093166004026101000a928302191660e087901c929092029190911790556001600160e01b031984166000818152602260209081526040808320805460ff1916909517909455835192835282810184815285519484019490945284516001600160a01b038716947fb1c6e929e0b0638c228622a32f1f2fb3375541d8faa4a0176173b50b4bfc75ea9489948894919360608501928601918190849084905b83811015611a24578181015183820152602001611a0c565b50505050905090810190601f168015611a515780820380516001836020036101000a031916815260200191505b50935050505060405180910390a2505050565b60076001600160a01b038216331415611ad65760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50336000818152601c602090815260408083206001600160a01b0386168085529252808320805460ff191690555190917f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa191a350565b6000826040516020018082805190602001908083835b60208310611b615780518252601f199092019160209182019101611b42565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f19018352808552825192909101919091206329965a1d60e01b8252306004830152602482018190526001600160a01b03881660448301529251929550731820a4b7618bde71dce8cdc73aab6c95905fad2494506329965a1d9350606480820193600093509182900301818387803b158015611c0257600080fd5b505af1158015611c16573d6000803e3d6000fd5b50505050505050565b6001600080836040516020018082805190602001908083835b60208310611c575780518252601f199092019160209182019101611c38565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60066001600160a01b038316611d295760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50601454611d3d908263ffffffff61253116565b601455611d4c8260008361267d565b611d7d6000801b846000858560405180602001604052806000815250604051806020016040528060008152506127c7565b604080518281526020810182905260008183015290516001600160a01b0380851692908616917fbcd28e05e57d4bcd5bfcc92a4661d412893e6112c44a2e25d96cfdfc30d5f22e9181900360800190a36040805182815290516001600160a01b038416916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3604080516001600160a01b038581168252602082018490526080828401819052600090830181905260c06060840181905283018190529251908516929182917fff4e9a26af4eb73b8bacfaa4abd4fea03d9448e7b912dc5ff4019048875aa2d4918190036101000190a4505050565b60056001600160a01b038416611eec5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b5060076001600160a01b038316611f5c5760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506000848152601d602090815260408083206001600160a01b038088168086529184528285209087168086529084529382902085905581518581529151909288927ff061499aa77c2f6f5e25e34955a06623705344a88256cc861a121ec0bce5cfec929081900390910190a48361201957816001600160a01b0316836001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a35b50505050565b6000610df583836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612c43565b600060066001600160a01b0386166120d25760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b50866001600160a01b0316866001600160a01b03161461226b576120f788888861258b565b8061213057506000888152601d602090815260408083206001600160a01b03808b168552908352818420908b1684529091529020548411155b6004906121965760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506000888152601d602090815260408083206001600160a01b03808b168552908352818420908b168452909152902054841161223b576000888152601d602090815260408083206001600160a01b03808b168552908352818420908b16845290915290205461220b908563ffffffff61201f16565b6000898152601d602090815260408083206001600160a01b038b168452825280832033845290915290205561226b565b6000888152601d602090815260408083206001600160a01b03808b168552908352818420908b1684529091528120555b61227a88888888888888612cda565b6001600160a01b0386166000908152601b602090815260408083208b84529091529020546003908511156123075760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b506000612314848a6130d6565b9050612321878a8761312b565b61232c86828761267d565b61233b818989898989896127c7565b856001600160a01b0316876001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef876040518082815260200191505060405180910390a3856001600160a01b0316876001600160a01b03168a7fff4e9a26af4eb73b8bacfaa4abd4fea03d9448e7b912dc5ff4019048875aa2d48b89898960405180856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b8381101561241f578181015183820152602001612407565b50505050905090810190601f16801561244c5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561247f578181015183820152602001612467565b50505050905090810190601f1680156124ac5780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390a48881146124fc5760408051868152905182918b917f67c8ba31d2dd11f1384577b3405b04ed91eed1231e408432ad2458cab37b2fa19181900360200190a35b98975050505050505050565b6125296000801b868686868660405180602001604052806000815250612061565b505050505050565b600082820183811015610df5576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061259783836125e0565b806125cf57506001600160a01b038083166000908152601e6020908152604080832088845282528083209387168352929052205460ff165b806111595750611159848484613347565b6000816001600160a01b0316836001600160a01b03161480610df55750506001600160a01b039081166000908152601c602090815260408083209490931682529290925290205460ff1690565b604080517f416d70506172746974696f6e537472617465677956616c696461746f7200000060208201526001600160e01b031992909216603d830152805180830360210181526041909201905290565b80612687576127c2565b6001600160a01b0383166000908152601560205260409020546126b0908263ffffffff61253116565b6001600160a01b038416600090815260156020908152604080832093909355601a815282822085835290522054612725576001600160a01b03831660008181526019602090815260408083208054600181018255818552838520018790559383529254601a8252838320868452909152919020555b6001600160a01b0383166000908152601b60209081526040808320858452909152902054612759908263ffffffff61253116565b6001600160a01b0384166000908152601b60209081526040808320868452825280832093909355601790522054612793576127938261343c565b6000828152601860205260409020546127b2908263ffffffff61253116565b6000838152601860205260409020555b505050565b60006127d28861347e565b6001600160e01b0319811660009081526022602052604090205490915060ff16156129d057600061280b306128068461262d565b613481565b90506001600160a01b038116156129ca57806001600160a01b031663b3c46f426000356001600160e01b0319168b8b8b8b8b8b8b6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b838110156128fd5781810151838201526020016128e5565b50505050905090810190601f16801561292a5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561295d578181015183820152602001612945565b50505050905090810190601f16801561298a5780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b1580156129b157600080fd5b505af11580156129c5573d6000803e3d6000fd5b505050505b50612a43565b600c6001600160e01b0319821615612a415760405162461bcd60e51b8152602060048201908152825460026000196101006001841615020190911604602483018190529091829160449091019084908015610af15780601f10610ac657610100808354040283529160200191610af1565b505b6000612a798660405180604001604052806012815260200171105b5c151bdad95b9cd49958da5c1a595b9d60721b815250613481565b90506001600160a01b03811615612c3857806001600160a01b0316638240ef486000356001600160e01b0319168b8b8b8b8b8b8b6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612b6b578181015183820152602001612b53565b50505050905090810190601f168015612b985780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612bcb578181015183820152602001612bb3565b50505050905090810190601f168015612bf85780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b158015612c1f57600080fd5b505af1158015612c33573d6000803e3d6000fd5b505050505b505050505050505050565b60008184841115612cd25760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015612c97578181015183820152602001612c7f565b50505050905090810190601f168015612cc45780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b6000612d0d866040518060400160405280600f81526020016e20b6b82a37b5b2b739a9b2b73232b960891b815250613481565b90506001600160a01b03811615612ecc57806001600160a01b031663ec3bb2886000356001600160e01b0319168a8a8a8a8a8a8a6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612dff578181015183820152602001612de7565b50505050905090810190601f168015612e2c5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015612e5f578181015183820152602001612e47565b50505050905090810190601f168015612e8c5780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b158015612eb357600080fd5b505af1158015612ec7573d6000803e3d6000fd5b505050505b6000612ed78961347e565b6001600160e01b0319811660009081526022602052604090205490915060ff1615612c38576000612f0b306128068461262d565b90506001600160a01b038116156130ca57806001600160a01b031663dc86ad7a6000356001600160e01b0319168c8c8c8c8c8c8c6040518963ffffffff1660e01b815260040180896001600160e01b0319166001600160e01b0319168152602001888152602001876001600160a01b03166001600160a01b03168152602001866001600160a01b03166001600160a01b03168152602001856001600160a01b03166001600160a01b031681526020018481526020018060200180602001838103835285818151815260200191508051906020019080838360005b83811015612ffd578181015183820152602001612fe5565b50505050905090810190601f16801561302a5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561305d578181015183820152602001613045565b50505050905090810190601f16801561308a5780820380516001836020036101000a031916815260200191505b509a5050505050505050505050600060405180830381600087803b1580156130b157600080fd5b505af11580156130c5573d6000803e3d6000fd5b505050505b50505050505050505050565b60006040835110156130e9575080610ce9565b60008084806020019051604081101561310157600080fd5b5080516020909101519092509050600019821415613122579150610ce99050565b50919392505050565b80613135576127c2565b6001600160a01b03831660009081526015602052604090205461315e908263ffffffff61201f16565b6001600160a01b038416600090815260156020908152604080832093909355601b81528282208583529052205461319b908263ffffffff61201f16565b6001600160a01b0384166000908152601b602090815260408083208684528252808320939093556018905220546131d8908263ffffffff61201f16565b60008381526018602052604090208190551580156131f557508115155b156132035761320382613584565b6001600160a01b0383166000908152601b602090815260408083208584529091529020546127c2576001600160a01b0383166000908152601a602090815260408083208584529091529020548061325a57506127c2565b6001600160a01b03841660009081526019602052604081208054600019810190811061328257fe5b906000526020600020015490508060196000876001600160a01b03166001600160a01b0316815260200190815260200160002060018403815481106132c357fe5b60009182526020808320909101929092556001600160a01b038716808252601a83526040808320858452845280832086905590825260199092522080548061330757fe5b6000828152602080822083016000199081018390559092019092556001600160a01b0387168252601a815260408083208784529091528120555050505050565b6000806133538561347e565b6001600160e01b0319811660009081526022602052604090205490915060ff16613381576000915050610df5565b6000613390306128068461262d565b90506001600160a01b038116156134305760408051633f0413df60e01b8152600481018890526001600160a01b0387811660248301528681166044830152915191831691633f0413df91606480820192602092909190829003018186803b1580156133fa57600080fd5b505afa15801561340e573d6000803e3d6000fd5b505050506040513d602081101561342457600080fd5b50519250610df5915050565b50600095945050505050565b601680546001810182557fd833147d7dc355ba459fc788f669e58cfaf9dc25ddcd0702e87d69c7b5124289018290555460009182526017602052604090912055565b90565b600080826040516020018082805190602001908083835b602083106134b75780518252601f199092019160209182019101613498565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f1901835280855282519282019290922063555ddc6560e11b83526001600160a01b038b166004840152602483018190529351939650731820a4b7618bde71dce8cdc73aab6c95905fad24955063aabbb8ca94506044808301949193509091829003018186803b15801561355057600080fd5b505afa158015613564573d6000803e3d6000fd5b505050506040513d602081101561357a57600080fd5b5051949350505050565b6000818152601760205260409020548061359e5750613627565b601680546000919060001981019081106135b457fe5b9060005260206000200154905080601660018403815481106135d257fe5b600091825260208083209091019290925582815260179091526040902082905560168054806135fd57fe5b60008281526020808220830160001990810183905590920190925584825260179052604081205550505b5056fea264697066735822122046f1197cc0a6e3d6399ed22c3480b4059302d3180614e1c23cf41dc5ac02219764736f6c634300060a0033
Verified Source Code Partial Match
Compiler: v0.6.10+commit.00c0fcaf
EVM: istanbul
Optimization: Yes (200 runs)
Amp.sol 2111 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.6.10;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers. Reverts with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
// Solidity only automatically asserts when dividing by 0
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
}
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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 `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, 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 `sender` to `recipient` 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 sender, address recipient, uint256 amount) external returns (bool);
/**
* @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);
}
/**
* @title Ownable is a contract the provides contract ownership functionality, including a two-
* phase transfer.
*/
contract Ownable {
address private _owner;
address private _authorizedNewOwner;
/**
* @notice Emitted when the owner authorizes ownership transfer to a new address
* @param authorizedAddress New owner address
*/
event OwnershipTransferAuthorization(address indexed authorizedAddress);
/**
* @notice Emitted when the authorized address assumed ownership
* @param oldValue Old owner
* @param newValue New owner
*/
event OwnerUpdate(address indexed oldValue, address indexed newValue);
/**
* @notice Sets the owner to the sender / contract creator
*/
constructor() internal {
_owner = msg.sender;
}
/**
* @notice Retrieves the owner of the contract
* @return The contract owner
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @notice Retrieves the authorized new owner of the contract
* @return The authorized new contract owner
*/
function authorizedNewOwner() public view returns (address) {
return _authorizedNewOwner;
}
/**
* @notice Authorizes the transfer of ownership from owner to the provided address.
* NOTE: No transfer will occur unless authorizedAddress calls assumeOwnership().
* This authorization may be removed by another call to this function authorizing the zero
* address.
* @param _authorizedAddress The address authorized to become the new owner
*/
function authorizeOwnershipTransfer(address _authorizedAddress) external {
require(msg.sender == _owner, "Invalid sender");
_authorizedNewOwner = _authorizedAddress;
emit OwnershipTransferAuthorization(_authorizedNewOwner);
}
/**
* @notice Transfers ownership of this contract to the _authorizedNewOwner
* @dev Error invalid sender.
*/
function assumeOwnership() external {
require(msg.sender == _authorizedNewOwner, "Invalid sender");
address oldValue = _owner;
_owner = _authorizedNewOwner;
_authorizedNewOwner = address(0);
emit OwnerUpdate(oldValue, _owner);
}
}
abstract contract ERC1820Registry {
function setInterfaceImplementer(
address _addr,
bytes32 _interfaceHash,
address _implementer
) external virtual;
function getInterfaceImplementer(address _addr, bytes32 _interfaceHash)
external
virtual
view
returns (address);
function setManager(address _addr, address _newManager) external virtual;
function getManager(address _addr) public virtual view returns (address);
}
/// Base client to interact with the registry.
contract ERC1820Client {
ERC1820Registry constant ERC1820REGISTRY = ERC1820Registry(
0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24
);
function setInterfaceImplementation(
string memory _interfaceLabel,
address _implementation
) internal {
bytes32 interfaceHash = keccak256(abi.encodePacked(_interfaceLabel));
ERC1820REGISTRY.setInterfaceImplementer(
address(this),
interfaceHash,
_implementation
);
}
function interfaceAddr(address addr, string memory _interfaceLabel)
internal
view
returns (address)
{
bytes32 interfaceHash = keccak256(abi.encodePacked(_interfaceLabel));
return ERC1820REGISTRY.getInterfaceImplementer(addr, interfaceHash);
}
function delegateManagement(address _newManager) internal {
ERC1820REGISTRY.setManager(address(this), _newManager);
}
}
contract ERC1820Implementer {
/**
* @dev ERC1820 well defined magic value indicating the contract has
* registered with the ERC1820Registry that it can implement an interface.
*/
bytes32 constant ERC1820_ACCEPT_MAGIC = keccak256(
abi.encodePacked("ERC1820_ACCEPT_MAGIC")
);
/**
* @dev Mapping of interface name keccak256 hashes for which this contract
* implements the interface.
* @dev Only settable internally.
*/
mapping(bytes32 => bool) internal _interfaceHashes;
/**
* @notice Indicates whether the contract implements the interface `_interfaceHash`
* for the address `_addr`.
* @param _interfaceHash keccak256 hash of the name of the interface.
* @return ERC1820_ACCEPT_MAGIC only if the contract implements `ìnterfaceHash`
* for the address `_addr`.
* @dev In this implementation, the `_addr` (the address for which the
* contract will implement the interface) is always `address(this)`.
*/
function canImplementInterfaceForAddress(
bytes32 _interfaceHash,
address // Comments to avoid compilation warnings for unused variables. /*addr*/
) external view returns (bytes32) {
if (_interfaceHashes[_interfaceHash]) {
return ERC1820_ACCEPT_MAGIC;
} else {
return "";
}
}
/**
* @notice Internally set the fact this contract implements the interface
* identified by `_interfaceLabel`
* @param _interfaceLabel String representation of the interface.
*/
function _setInterface(string memory _interfaceLabel) internal {
_interfaceHashes[keccak256(abi.encodePacked(_interfaceLabel))] = true;
}
}
/**
* @title IAmpTokensSender
* @dev IAmpTokensSender token transfer hook interface
*/
interface IAmpTokensSender {
/**
* @dev Report if the transfer will succeed from the pespective of the
* token sender
*/
function canTransfer(
bytes4 functionSig,
bytes32 partition,
address operator,
address from,
address to,
uint256 value,
bytes calldata data,
bytes calldata operatorData
) external view returns (bool);
/**
* @dev Hook executed upon a transfer on behalf of the sender
*/
function tokensToTransfer(
bytes4 functionSig,
bytes32 partition,
address operator,
address from,
address to,
uint256 value,
bytes calldata data,
bytes calldata operatorData
) external;
}
/**
* @title IAmpTokensRecipient
* @dev IAmpTokensRecipient token transfer hook interface
*/
interface IAmpTokensRecipient {
/**
* @dev Report if the recipient will successfully receive the tokens
*/
function canReceive(
bytes4 functionSig,
bytes32 partition,
address operator,
address from,
address to,
uint256 value,
bytes calldata data,
bytes calldata operatorData
) external view returns (bool);
/**
* @dev Hook executed upon a transfer to the recipient
*/
function tokensReceived(
bytes4 functionSig,
bytes32 partition,
address operator,
address from,
address to,
uint256 value,
bytes calldata data,
bytes calldata operatorData
) external;
}
/**
* @notice Partition strategy validator hooks for Amp
*/
interface IAmpPartitionStrategyValidator {
function tokensFromPartitionToValidate(
bytes4 _functionSig,
bytes32 _partition,
address _operator,
address _from,
address _to,
uint256 _value,
bytes calldata _data,
bytes calldata _operatorData
) external;
function tokensToPartitionToValidate(
bytes4 _functionSig,
bytes32 _partition,
address _operator,
address _from,
address _to,
uint256 _value,
bytes calldata _data,
bytes calldata _operatorData
) external;
function isOperatorForPartitionScope(
bytes32 _partition,
address _operator,
address _tokenHolder
) external view returns (bool);
}
/**
* @title PartitionUtils
* @notice Partition related helper functions.
*/
library PartitionUtils {
bytes32 public constant CHANGE_PARTITION_FLAG = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
/**
* @notice Retrieve the destination partition from the 'data' field.
* A partition change is requested ONLY when 'data' starts with the flag:
*
* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
*
* When the flag is detected, the destination partition is extracted from the
* 32 bytes following the flag.
* @param _data Information attached to the transfer. Will contain the
* destination partition if a change is requested.
* @param _fallbackPartition Partition value to return if a partition change
* is not requested in the `_data`.
* @return toPartition Destination partition. If the `_data` does not contain
* the prefix and bytes32 partition in the first 64 bytes, the method will
* return the provided `_fromPartition`.
*/
function _getDestinationPartition(bytes memory _data, bytes32 _fallbackPartition)
internal
pure
returns (bytes32)
{
if (_data.length < 64) {
return _fallbackPartition;
}
(bytes32 flag, bytes32 toPartition) = abi.decode(_data, (bytes32, bytes32));
if (flag == CHANGE_PARTITION_FLAG) {
return toPartition;
}
return _fallbackPartition;
}
/**
* @notice Helper to get the strategy identifying prefix from the `_partition`.
* @param _partition Partition to get the prefix for.
* @return 4 byte partition strategy prefix.
*/
function _getPartitionPrefix(bytes32 _partition) internal pure returns (bytes4) {
return bytes4(_partition);
}
/**
* @notice Helper method to split the partition into the prefix, sub partition
* and partition owner components.
* @param _partition The partition to split into parts.
* @return The 4 byte partition prefix, 8 byte sub partition, and final 20
* bytes representing an address.
*/
function _splitPartition(bytes32 _partition)
internal
pure
returns (
bytes4,
bytes8,
address
)
{
bytes4 prefix = bytes4(_partition);
bytes8 subPartition = bytes8(_partition << 32);
address addressPart = address(uint160(uint256(_partition)));
return (prefix, subPartition, addressPart);
}
/**
* @notice Helper method to get a partition strategy ERC1820 interface name
* based on partition prefix.
* @param _prefix 4 byte partition prefix.
* @dev Each 4 byte prefix has a unique interface name so that an individual
* hook implementation can be set for each prefix.
*/
function _getPartitionStrategyValidatorIName(bytes4 _prefix)
internal
pure
returns (string memory)
{
return string(abi.encodePacked("AmpPartitionStrategyValidator", _prefix));
}
}
/**
* @title ErrorCodes
* @notice Amp error codes.
*/
contract ErrorCodes {
string internal EC_50_TRANSFER_FAILURE = "50";
string internal EC_51_TRANSFER_SUCCESS = "51";
string internal EC_52_INSUFFICIENT_BALANCE = "52";
string internal EC_53_INSUFFICIENT_ALLOWANCE = "53";
string internal EC_56_INVALID_SENDER = "56";
string internal EC_57_INVALID_RECEIVER = "57";
string internal EC_58_INVALID_OPERATOR = "58";
string internal EC_59_INSUFFICIENT_RIGHTS = "59";
string internal EC_5A_INVALID_SWAP_TOKEN_ADDRESS = "5A";
string internal EC_5B_INVALID_VALUE_0 = "5B";
string internal EC_5C_ADDRESS_CONFLICT = "5C";
string internal EC_5D_PARTITION_RESERVED = "5D";
string internal EC_5E_PARTITION_PREFIX_CONFLICT = "5E";
string internal EC_5F_INVALID_PARTITION_PREFIX_0 = "5F";
string internal EC_60_SWAP_TRANSFER_FAILURE = "60";
}
interface ISwapToken {
function allowance(address owner, address spender)
external
view
returns (uint256 remaining);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool success);
}
/**
* @title Amp
* @notice Amp is an ERC20 compatible collateral token designed to support
* multiple classes of collateralization systems.
* @dev The Amp token contract includes the following features:
*
* Partitions
* Tokens can be segmented within a given address by "partition", which in
* pracice is a 32 byte identifier. These partitions can have unique
* permissions globally, through the using of partition strategies, and
* locally, on a per address basis. The ability to create the sub-segments
* of tokens and assign special behavior gives collateral managers
* flexibility in how they are implemented.
*
* Operators
* Inspired by ERC777, Amp allows token holders to assign "operators" on
* all (or any number of partitions) of their tokens. Operators are allowed
* to execute transfers on behalf of token owners without the need to use the
* ERC20 "allowance" semantics.
*
* Transfers with Data
* Inspired by ERC777, Amp transfers can include arbitrary data, as well as
* operator data. This data can be used to change the partition of tokens,
* be used by collateral manager hooks to validate a transfer, be propagated
* via event to an off chain system, etc.
*
* Token Transfer Hooks on Send and Receive
* Inspired by ERC777, Amp uses the ERC1820 Registry to allow collateral
* manager implementations to register hooks to be called upon sending to
* or transferring from the collateral manager's address or, using partition
* strategies, owned partition space. The hook implementations can be used
* to validate transfer properties, gate transfers, emit custom events,
* update local state, etc.
*
* Collateral Management Partition Strategies
* Amp is able to define certain sets of partitions, identified by a 4 byte
* prefix, that will allow special, custom logic to be executed when transfers
* are made to or from those partitions. This opens up the possibility of
* entire classes of collateral management systems that would not be possible
* without it.
*
* These features give collateral manager implementers flexibility while
* providing a consistent, "collateral-in-place", interface for interacting
* with collateral systems directly through the Amp contract.
*/
contract Amp is IERC20, ERC1820Client, ERC1820Implementer, ErrorCodes, Ownable {
using SafeMath for uint256;
/**************************************************************************/
/********************** ERC1820 Interface Constants ***********************/
/**
* @dev AmpToken interface label.
*/
string internal constant AMP_INTERFACE_NAME = "AmpToken";
/**
* @dev ERC20Token interface label.
*/
string internal constant ERC20_INTERFACE_NAME = "ERC20Token";
/**
* @dev AmpTokensSender interface label.
*/
string internal constant AMP_TOKENS_SENDER = "AmpTokensSender";
/**
* @dev AmpTokensRecipient interface label.
*/
string internal constant AMP_TOKENS_RECIPIENT = "AmpTokensRecipient";
/**
* @dev AmpTokensChecker interface label.
*/
string internal constant AMP_TOKENS_CHECKER = "AmpTokensChecker";
/**************************************************************************/
/*************************** Token properties *****************************/
/**
* @dev Token name (Amp).
*/
string internal _name;
/**
* @dev Token symbol (AMP).
*/
string internal _symbol;
/**
* @dev Total minted supply of token. This will increase comensurately with
* successful swaps of the swap token.
*/
uint256 internal _totalSupply;
/**
* @dev The granularity of the token. Hard coded to 1.
*/
uint256 internal constant _granularity = 1;
/**************************************************************************/
/***************************** Token mappings *****************************/
/**
* @dev Mapping from tokenHolder to balance. This reflects the balance
* across all partitions of an address.
*/
mapping(address => uint256) internal _balances;
/**************************************************************************/
/************************** Partition mappings ****************************/
/**
* @dev List of active partitions. This list reflects all partitions that
* have tokens assigned to them.
*/
bytes32[] internal _totalPartitions;
/**
* @dev Mapping from partition to their index.
*/
mapping(bytes32 => uint256) internal _indexOfTotalPartitions;
/**
* @dev Mapping from partition to global balance of corresponding partition.
*/
mapping(bytes32 => uint256) public totalSupplyByPartition;
/**
* @dev Mapping from tokenHolder to their partitions.
*/
mapping(address => bytes32[]) internal _partitionsOf;
/**
* @dev Mapping from (tokenHolder, partition) to their index.
*/
mapping(address => mapping(bytes32 => uint256)) internal _indexOfPartitionsOf;
/**
* @dev Mapping from (tokenHolder, partition) to balance of corresponding
* partition.
*/
mapping(address => mapping(bytes32 => uint256)) internal _balanceOfByPartition;
/**
* @notice Default partition of the token.
* @dev All ERC20 operations operate solely on this partition.
*/
bytes32
public constant defaultPartition = 0x0000000000000000000000000000000000000000000000000000000000000000;
/**
* @dev Zero partition prefix. Parititions with this prefix can not have
* a strategy assigned, and partitions with a different prefix must have one.
*/
bytes4 internal constant ZERO_PREFIX = 0x00000000;
/**************************************************************************/
/***************************** Operator mappings **************************/
/**
* @dev Mapping from (tokenHolder, operator) to authorized status. This is
* specific to the token holder.
*/
mapping(address => mapping(address => bool)) internal _authorizedOperator;
/**************************************************************************/
/********************** Partition operator mappings ***********************/
/**
* @dev Mapping from (partition, tokenHolder, spender) to allowed value.
* This is specific to the token holder.
*/
mapping(bytes32 => mapping(address => mapping(address => uint256)))
internal _allowedByPartition;
/**
* @dev Mapping from (tokenHolder, partition, operator) to 'approved for
* partition' status. This is specific to the token holder.
*/
mapping(address => mapping(bytes32 => mapping(address => bool)))
internal _authorizedOperatorByPartition;
/**************************************************************************/
/********************** Collateral Manager mappings ***********************/
/**
* @notice Collection of registered collateral managers.
*/
address[] public collateralManagers;
/**
* @dev Mapping of collateral manager addresses to registration status.
*/
mapping(address => bool) internal _isCollateralManager;
/**************************************************************************/
/********************* Partition Strategy mappings ************************/
/**
* @notice Collection of reserved partition strategies.
*/
bytes4[] public partitionStrategies;
/**
* @dev Mapping of partition strategy flag to registration status.
*/
mapping(bytes4 => bool) internal _isPartitionStrategy;
/**************************************************************************/
/***************************** Swap storage *******************************/
/**
* @notice Swap token address. Immutable.
*/
ISwapToken public swapToken;
/**
* @notice Swap token graveyard address.
* @dev This is the address that the incoming swapped tokens will be
* forwarded to upon successfully minting Amp.
*/
address
public constant swapTokenGraveyard = 0x000000000000000000000000000000000000dEaD;
/**************************************************************************/
/** EVENTS ****************************************************************/
/**************************************************************************/
/**************************************************************************/
/**************************** Transfer Events *****************************/
/**
* @notice Emitted when a transfer has been successfully completed.
* @param fromPartition The partition the tokens were transfered from.
* @param operator The address that initiated the transfer.
* @param from The address the tokens were transferred from.
* @param to The address the tokens were transferred to.
* @param value The amount of tokens transferred.
* @param data Additional metadata included with the transfer. Can include
* the partition the tokens were transferred to (if different than
* `fromPartition`).
* @param operatorData Additional metadata included with the transfer on
* behalf of the operator.
*/
event TransferByPartition(
bytes32 indexed fromPartition,
address operator,
address indexed from,
address indexed to,
uint256 value,
bytes data,
bytes operatorData
);
/**
* @notice Emitted when a transfer has been successfully completed and the
* tokens that were transferred have changed partitions.
* @param fromPartition The partition the tokens were transfered from.
* @param toPartition The partition the tokens were transfered to.
* @param value The amount of tokens transferred.
*/
event ChangedPartition(
bytes32 indexed fromPartition,
bytes32 indexed toPartition,
uint256 value
);
/**************************************************************************/
/**************************** Operator Events *****************************/
/**
* @notice Emitted when a token holder specifies an amount of tokens in a
* a partition that an operator can transfer.
* @param partition The partition of the tokens the holder has authorized the
* operator to transfer from.
* @param owner The token holder.
* @param spender The operator the `owner` has authorized the allowance for.
*/
event ApprovalByPartition(
bytes32 indexed partition,
address indexed owner,
address indexed spender,
uint256 value
);
/**
* @notice Emitted when a token holder has authorized an operator for their
* tokens.
* @dev This event applies to the token holder address across all partitions.
* @param operator The address that was authorized to transfer tokens on
* behalf of the `tokenHolder`.
* @param tokenHolder The address that authorized the `operator` to transfer
* their tokens.
*/
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
/**
* @notice Emitted when a token holder has de-authorized an operator from
* transferring their tokens.
* @dev This event applies to the token holder address across all partitions.
* @param operator The address that was de-authorized from transferring tokens
* on behalf of the `tokenHolder`.
* @param tokenHolder The address that revoked the `operator`'s permission
* to transfer their tokens.
*/
event RevokedOperator(address indexed operator, address indexed tokenHolder);
/**
* @notice Emitted when a token holder has authorized an operator to transfer
* their tokens of one partition.
* @param partition The partition the `operator` is allowed to transfer
* tokens from.
* @param operator The address that was authorized to transfer tokens on
* behalf of the `tokenHolder`.
* @param tokenHolder The address that authorized the `operator` to transfer
* their tokens in `partition`.
*/
event AuthorizedOperatorByPartition(
bytes32 indexed partition,
address indexed operator,
address indexed tokenHolder
);
/**
* @notice Emitted when a token holder has de-authorized an operator from
* transferring their tokens from a specific partition.
* @param partition The partition the `operator` is no longer allowed to
* transfer tokens from on behalf of the `tokenHolder`.
* @param operator The address that was de-authorized from transferring
* tokens on behalf of the `tokenHolder`.
* @param tokenHolder The address that revoked the `operator`'s permission
* to transfer their tokens from `partition`.
*/
event RevokedOperatorByPartition(
bytes32 indexed partition,
address indexed operator,
address indexed tokenHolder
);
/**************************************************************************/
/********************** Collateral Manager Events *************************/
/**
* @notice Emitted when a collateral manager has been registered.
* @param collateralManager The address of the collateral manager.
*/
event CollateralManagerRegistered(address collateralManager);
/**************************************************************************/
/*********************** Partition Strategy Events ************************/
/**
* @notice Emitted when a new partition strategy validator is set.
* @param flag The 4 byte prefix of the partitions that the stratgy affects.
* @param name The name of the partition strategy.
* @param implementation The address of the partition strategy hook
* implementation.
*/
event PartitionStrategySet(bytes4 flag, string name, address indexed implementation);
// ************** Mint & Swap **************
/**
* @notice Emitted when tokens are minted as a result of a token swap
* @param operator Address that executed the swap that resulted in tokens being minted
* @param to Address that received the newly minted tokens.
* @param value Amount of tokens minted
* @param data Empty bytes, required for interface compatibility
*/
event Minted(address indexed operator, address indexed to, uint256 value, bytes data);
/**
* @notice Indicates tokens swapped for Amp.
* @dev The tokens that are swapped for Amp will be transferred to a
* graveyard address that is for all practical purposes inaccessible.
* @param operator Address that executed the swap.
* @param from Address that the tokens were swapped from, and Amp minted for.
* @param value Amount of tokens swapped into Amp.
*/
event Swap(address indexed operator, address indexed from, uint256 value);
/**************************************************************************/
/** CONSTRUCTOR ***********************************************************/
/**************************************************************************/
/**
* @notice Initialize Amp, initialize the default partition, and register the
* contract implementation in the global ERC1820Registry.
* @param _swapTokenAddress_ The address of the ERC20 token that is set to be
* swappable for Amp.
* @param _name_ Name of the token.
* @param _symbol_ Symbol of the token.
*/
constructor(
address _swapTokenAddress_,
string memory _name_,
string memory _symbol_
) public {
// "Swap token cannot be 0 address"
require(_swapTokenAddress_ != address(0), EC_5A_INVALID_SWAP_TOKEN_ADDRESS);
swapToken = ISwapToken(_swapTokenAddress_);
_name = _name_;
_symbol = _symbol_;
_totalSupply = 0;
// Add the default partition to the total partitions on deploy
_addPartitionToTotalPartitions(defaultPartition);
// Register contract in ERC1820 registry
ERC1820Client.setInterfaceImplementation(AMP_INTERFACE_NAME, address(this));
ERC1820Client.setInterfaceImplementation(ERC20_INTERFACE_NAME, address(this));
// Indicate token verifies Amp and ERC20 interfaces
ERC1820Implementer._setInterface(AMP_INTERFACE_NAME);
ERC1820Implementer._setInterface(ERC20_INTERFACE_NAME);
}
/**************************************************************************/
/** EXTERNAL FUNCTIONS (ERC20) ********************************************/
/**************************************************************************/
/**
* @notice Get the total number of issued tokens.
* @return Total supply of tokens currently in circulation.
*/
function totalSupply() external override view returns (uint256) {
return _totalSupply;
}
/**
* @notice Get the balance of the account with address `_tokenHolder`.
* @dev This returns the balance of the holder across all partitions. Note
* that due to other functionality in Amp, this figure should not be used
* as the arbiter of the amount a token holder will successfully be able to
* send via the ERC20 compatible `transfer` method. In order to get that
* figure, use `balanceOfByParition` and to get the balance of the default
* partition.
* @param _tokenHolder Address for which the balance is returned.
* @return Amount of token held by `_tokenHolder` in the default partition.
*/
function balanceOf(address _tokenHolder) external override view returns (uint256) {
return _balances[_tokenHolder];
}
/**
* @notice Transfer token for a specified address.
* @dev This method is for ERC20 compatibility, and only affects the
* balance of the `msg.sender` address's default partition.
* @param _to The address to transfer to.
* @param _value The value to be transferred.
* @return A boolean that indicates if the operation was successful.
*/
function transfer(address _to, uint256 _value) external override returns (bool) {
_transferByDefaultPartition(msg.sender, msg.sender, _to, _value, "");
return true;
}
/**
* @notice Transfer tokens from one address to another.
* @dev This method is for ERC20 compatibility, and only affects the
* balance and allowance of the `_from` address's default partition.
* @param _from The address which you want to transfer tokens from.
* @param _to The address which you want to transfer to.
* @param _value The amount of tokens to be transferred.
* @return A boolean that indicates if the operation was successful.
*/
function transferFrom(
address _from,
address _to,
uint256 _value
) external override returns (bool) {
_transferByDefaultPartition(msg.sender, _from, _to, _value, "");
return true;
}
/**
* @notice Check the value of tokens that an owner allowed to a spender.
* @dev This method is for ERC20 compatibility, and only affects the
* allowance of the `msg.sender`'s default partition.
* @param _owner address The address which owns the funds.
* @param _spender address The address which will spend the funds.
* @return A uint256 specifying the value of tokens still available for the
* spender.
*/
function allowance(address _owner, address _spender)
external
override
view
returns (uint256)
{
return _allowedByPartition[defaultPartition][_owner][_spender];
}
/**
* @notice Approve the passed address to spend the specified amount of
* tokens from the default partition on behalf of 'msg.sender'.
* @dev This method is for ERC20 compatibility, and only affects the
* allowance of the `msg.sender`'s default partition.
* @param _spender The address which will spend the funds.
* @param _value The amount of tokens to be spent.
* @return A boolean that indicates if the operation was successful.
*/
function approve(address _spender, uint256 _value) external override returns (bool) {
_approveByPartition(defaultPartition, msg.sender, _spender, _value);
return true;
}
/**
* @notice Atomically increases the allowance granted to `_spender` by the
* for caller.
* @dev This is an alternative to {approve} that can be used as a mitigation
* problems described in {IERC20-approve}.
* Emits an {Approval} event indicating the updated allowance.
* Requirements:
* - `_spender` cannot be the zero address.
* @dev This method is for ERC20 compatibility, and only affects the
* allowance of the `msg.sender`'s default partition.
* @param _spender Operator allowed to transfer the tokens
* @param _addedValue Additional amount of the `msg.sender`s tokens `_spender`
* is allowed to transfer
* @return 'true' is successful, 'false' otherwise
*/
function increaseAllowance(address _spender, uint256 _addedValue)
external
returns (bool)
{
_approveByPartition(
defaultPartition,
msg.sender,
_spender,
_allowedByPartition[defaultPartition][msg.sender][_spender].add(_addedValue)
);
return true;
}
/**
* @notice Atomically decreases the allowance granted to `_spender` by the
* caller.
* @dev This is an alternative to {approve} that can be used as a mitigation
* for bugs caused by reentrancy.
* Emits an {Approval} event indicating the updated allowance.
* Requirements:
* - `_spender` cannot be the zero address.
* - `_spender` must have allowance for the caller of at least
* `_subtractedValue`.
* @dev This method is for ERC20 compatibility, and only affects the
* allowance of the `msg.sender`'s default partition.
* @param _spender Operator allowed to transfer the tokens
* @param _subtractedValue Amount of the `msg.sender`s tokens `_spender`
* is no longer allowed to transfer
* @return 'true' is successful, 'false' otherwise
*/
function decreaseAllowance(address _spender, uint256 _subtractedValue)
external
returns (bool)
{
_approveByPartition(
defaultPartition,
msg.sender,
_spender,
_allowedByPartition[defaultPartition][msg.sender][_spender].sub(
_subtractedValue
)
);
return true;
}
/**************************************************************************/
/** EXTERNAL FUNCTIONS (AMP) **********************************************/
/**************************************************************************/
/******************************** Swap ***********************************/
/**
* @notice Swap tokens to mint AMP.
* @dev Requires `_from` to have given allowance of swap token to contract.
* Otherwise will throw error code 53 (Insuffient Allowance).
* @param _from Token holder to execute the swap for.
*/
function swap(address _from) public {
uint256 amount = swapToken.allowance(_from, address(this));
require(amount > 0, EC_53_INSUFFICIENT_ALLOWANCE);
require(
swapToken.transferFrom(_from, swapTokenGraveyard, amount),
EC_60_SWAP_TRANSFER_FAILURE
);
_mint(msg.sender, _from, amount);
emit Swap(msg.sender, _from, amount);
}
/**************************************************************************/
/************************** Holder information ****************************/
/**
* @notice Get balance of a tokenholder for a specific partition.
* @param _partition Name of the partition.
* @param _tokenHolder Address for which the balance is returned.
* @return Amount of token of partition `_partition` held by `_tokenHolder` in the token contract.
*/
function balanceOfByPartition(bytes32 _partition, address _tokenHolder)
external
view
returns (uint256)
{
return _balanceOfByPartition[_tokenHolder][_partition];
}
/**
* @notice Get partitions index of a token holder.
* @param _tokenHolder Address for which the partitions index are returned.
* @return Array of partitions index of '_tokenHolder'.
*/
function partitionsOf(address _tokenHolder) external view returns (bytes32[] memory) {
return _partitionsOf[_tokenHolder];
}
/**************************************************************************/
/************************** Advanced Transfers ****************************/
/**
* @notice Transfer tokens from a specific partition on behalf of a token
* holder, optionally changing the parittion and optionally including
* arbitrary data with the transfer.
* @dev This can be used to transfer an address's own tokens, or transfer
* a different addresses tokens by specifying the `_from` param. If
* attempting to transfer from a different address than `msg.sender`, the
* `msg.sender` will need to be an operator or have enough allowance for the
* `_partition` of the `_from` address.
* @param _partition Name of the partition to transfer from.
* @param _from Token holder.
* @param _to Token recipient.
* @param _value Number of tokens to transfer.
* @param _data Information attached to the transfer. Will contain the
* destination partition (if changing partitions).
* @param _operatorData Information attached to the transfer, by the operator.
* @return Destination partition.
*/
function transferByPartition(
bytes32 _partition,
address _from,
address _to,
uint256 _value,
bytes calldata _data,
bytes calldata _operatorData
) external returns (bytes32) {
return
_transferByPartition(
_partition,
msg.sender,
_from,
_to,
_value,
_data,
_operatorData
);
}
/**************************************************************************/
/************************** Operator Management ***************************/
/**
* @notice Set a third party operator address as an operator of 'msg.sender'
* to transfer and redeem tokens on its behalf.
* @dev The msg.sender is always an operator for itself, and does not need to
* be explicitly added.
* @param _operator Address to set as an operator for 'msg.sender'.
*/
function authorizeOperator(address _operator) external {
require(_operator != msg.sender, EC_58_INVALID_OPERATOR);
_authorizedOperator[msg.sender][_operator] = true;
emit AuthorizedOperator(_operator, msg.sender);
}
/**
* @notice Remove the right of the operator address to be an operator for
* 'msg.sender' and to transfer and redeem tokens on its behalf.
* @dev The msg.sender is always an operator for itself, and cannot be
* removed.
* @param _operator Address to rescind as an operator for 'msg.sender'.
*/
function revokeOperator(address _operator) external {
require(_operator != msg.sender, EC_58_INVALID_OPERATOR);
_authorizedOperator[msg.sender][_operator] = false;
emit RevokedOperator(_operator, msg.sender);
}
/**
* @notice Set `_operator` as an operator for 'msg.sender' for a given partition.
* @dev The msg.sender is always an operator for itself, and does not need to
* be explicitly added to a partition.
* @param _partition Name of the partition.
* @param _operator Address to set as an operator for 'msg.sender'.
*/
function authorizeOperatorByPartition(bytes32 _partition, address _operator)
external
{
require(_operator != msg.sender, EC_58_INVALID_OPERATOR);
_authorizedOperatorByPartition[msg.sender][_partition][_operator] = true;
emit AuthorizedOperatorByPartition(_partition, _operator, msg.sender);
}
/**
* @notice Remove the right of the operator address to be an operator on a
* given part...
// [truncated — 80206 bytes total]
Read Contract
allowance 0xdd62ed3e → uint256
allowanceByPartition 0x17ec83ca → uint256
authorizedNewOwner 0x5481eed3 → address
balanceOf 0x70a08231 → uint256
balanceOfByPartition 0x30e82803 → uint256
canImplementInterfaceForAddress 0x249cb3fa → bytes32
collateralManagers 0x814435af → address
decimals 0x313ce567 → uint8
defaultPartition 0x7e3a262d → bytes32
granularity 0x556f0dc7 → uint256
isCollateralManager 0x0e0e923b → bool
isOperator 0xb6363cf2 → bool
isOperatorForCollateralManager 0xaeb72e70 → bool
isOperatorForPartition 0x6d77cad6 → bool
isPartitionStrategy 0x900ff16d → bool
name 0x06fdde03 → string
owner 0x8da5cb5b → address
partitionStrategies 0x75deca02 → bytes4
partitionsOf 0x740ab8f4 → bytes32[]
swapToken 0xdc73e49c → address
swapTokenGraveyard 0xa0cf6b84 → address
symbol 0x95d89b41 → string
totalPartitions 0x69598efe → bytes32[]
totalSupply 0x18160ddd → uint256
totalSupplyByPartition 0xa26734dc → uint256
Write Contract 18 functions
These functions modify contract state and require a wallet transaction to execute.
approve 0x095ea7b3
address _spender
uint256 _value
returns: bool
approveByPartition 0x14d1e62f
bytes32 _partition
address _spender
uint256 _value
returns: bool
assumeOwnership 0xa2c1cae2
No parameters
authorizeOperator 0x959b8c3f
address _operator
authorizeOperatorByPartition 0x103ef9e1
bytes32 _partition
address _operator
authorizeOwnershipTransfer 0x87f4427e
address _authorizedAddress
decreaseAllowance 0xa457c2d7
address _spender
uint256 _subtractedValue
returns: bool
decreaseAllowanceByPartition 0x1ff6442e
bytes32 _partition
address _spender
uint256 _subtractedValue
returns: bool
increaseAllowance 0x39509351
address _spender
uint256 _addedValue
returns: bool
increaseAllowanceByPartition 0xc2f89a51
bytes32 _partition
address _spender
uint256 _addedValue
returns: bool
registerCollateralManager 0xb9d7b471
No parameters
revokeOperator 0xfad8b32a
address _operator
revokeOperatorByPartition 0x168ecec5
bytes32 _partition
address _operator
setPartitionStrategy 0xe30834e0
bytes4 _prefix
address _implementation
swap 0x03438dd0
address _from
transfer 0xa9059cbb
address _to
uint256 _value
returns: bool
transferByPartition 0x2036a94d
bytes32 _partition
address _from
address _to
uint256 _value
bytes _data
bytes _operatorData
returns: bytes32
transferFrom 0x23b872dd
address _from
address _to
uint256 _value
returns: bool
Top Interactions
| Address | Txns | Sent | Received |
|---|---|---|---|
| 0xA8A7D147...25fe | 1 | 1 |
Token Balances (2)
View Transfers →Recent Transactions
|
| Hash | Block | Age | From/To | Value | |
|---|---|---|---|---|---|
| 0x4ee0e9b1...7de2d2 | 24,584,032 | IN | 0xA8A7D147...25fe | 0 ETH |