Address Contract Partially Verified
Address
0x3eB6d865d407041b237E617eD5cd9A1286Da9350
Balance
0 ETH
Nonce
1
Code Size
19346 bytes
Creator
0x090A40Bb...f360 at tx 0x360788cb...37be65
Indexed Transactions
0
Contract Bytecode
19346 bytes
0x608060405234801561000f575f5ffd5b50600436106103d5575f3560e01c80638853ce8311610200578063a9059cbb1161011f578063dd62ed3e116100b4578063ee532f3111610084578063ee532f3114610906578063f2fde38b14610919578063f3d490db1461092c578063f698da251461093f578063fad8b32a14610947575f5ffd5b8063dd62ed3e14610895578063e77c646d146108cd578063ea74838a146108e0578063ec9a6e87146108f3575f5ffd5b8063bb3acde9116100ef578063bb3acde91461085f578063bcfdc0cf14610872578063c35018481461087a578063ca281fd91461088d575f5ffd5b8063a9059cbb14610804578063aa271e1a14610817578063b10d6b411461082a578063b6363cf21461084c575f5ffd5b80639675193c116101955780639fa5f50b116101655780639fa5f50b146107c2578063a26734dc146107ca578063a6f4f105146107e9578063a8082cb0146107fc575f5ffd5b80639675193c14610781578063983b2d561461079457806398650275146107a757806398ddcec7146107af575f5ffd5b806392127126116101d05780639212712614610740578063933964c714610753578063959b8c3f1461076657806395d89b4114610779575f5ffd5b80638853ce8314610700578063895d7386146103ee5780638c0dee9c146107135780638da5cb5b14610726575f5ffd5b806330e82803116102f75780636c23c7b01161028c578063715018a61161025c578063715018a6146106ab578063740ab8f4146106b35780637cc0c3a7146106c657806381552f58146106db578063861ed3ea146106ed575f5ffd5b80636c23c7b01461062f5780636c30d170146106685780636d77cad61461067057806370a0823114610683575f5ffd5b8063556f0dc7116102c7578063556f0dc7146105ec57806362eb0068146105f457806367c849191461060757806369598efe1461061a575f5ffd5b806330e8280314610589578063313ce567146105bb5780634c783bf5146105ca5780634d8fae95146105da575f5ffd5b806318160ddd1161036d578063249cb3fa1161033d578063249cb3fa1461053f5780632535f762146105525780632f1cae85146105655780633092afd514610576575f5ffd5b806318160ddd146104c65780631d43e1c0146104ce57806322400f4e146104eb57806323b872dd1461052c575f5ffd5b806314d1e62f116103a857806314d1e62f14610442578063168ecec51461045557806316e1aed41461046857806317ec83ca1461047b575f5ffd5b8063010648ca146103d957806306fdde03146103ee578063095ea7b31461040c578063103ef9e11461042f575b5f5ffd5b6103ec6103e7366004613ecc565b61095a565b005b6103f6610a8c565b6040516104039190613f48565b60405180910390f35b61041f61041a366004613f7e565b610b1c565b6040519015158152602001610403565b6103ec61043d366004613fa8565b610bb0565b61041f610450366004613fd6565b610c13565b6103ec610463366004613fa8565b610caa565b6103ec61047636600461404b565b610d0a565b6104b8610489366004614092565b5f9283526019602090815260408085206001600160a01b03948516865282528085209290931684525290205490565b604051908152602001610403565b6008546104b8565b6040805180820190915260018152603160f81b60208201526103f6565b6104b8604051752729a228afa222a320aaa62a2fa820a92a24aa24a7a760511b60208201526036016040516020818303038152906040528051906020012081565b61041f61053a3660046140d1565b610d53565b6104b861054d366004613fa8565b610e7a565b6103ec6105603660046140fe565b610ed7565b60095462010000900460ff1661041f565b6103ec610584366004614155565b610f31565b6104b8610597366004613fa8565b6001600160a01b03165f908152601460209081526040808320938352929052205490565b60405160128152602001610403565b600954610100900460ff1661041f565b6104b86a0d4dc73a9dcdb1faf4000081565b6007546104b8565b6103ec610602366004614170565b610f62565b6103ec6106153660046141a6565b610fba565b610622611062565b604051610403919061420a565b61064261063d36600461424c565b6110b7565b604080516001600160f81b03199094168452602084019290925290820152606001610403565b6103ec61119c565b61041f61067e366004614092565b6111b2565b6104b8610691366004614155565b6001600160a01b03165f908152600a602052604090205490565b6103ec6111c6565b6106226106c1366004614155565b6111d9565b6106ce611242565b6040516104039190614333565b6104b86a130165c173b822d438000081565b6106ce6106fb366004614345565b6112a1565b6103ec61070e366004614370565b611309565b6104b861072136600461424c565b611438565b5f546040516001600160a01b039091168152602001610403565b61064261074e3660046141a6565b6115d6565b6103ec610761366004614481565b611681565b6103ec610774366004614155565b611697565b6103f6611703565b6103ec61078f3660046140fe565b611712565b6103ec6107a2366004614155565b611851565b6103ec61187f565b6103ec6107bd3660046141a6565b611888565b610622611a10565b6104b86107d8366004614345565b5f9081526011602052604090205490565b6103ec6107f73660046144b4565b611a64565b6104b8611ab8565b61041f610812366004613f7e565b611b5a565b61041f610825366004614155565b611b8b565b61083d610838366004614345565b611b97565b60405161040393929190614535565b61041f61085a366004614559565b611c70565b6103ec61086d3660046140fe565b611c7b565b610622611d4e565b6103ec610888366004614345565b611da2565b6103ec612067565b6104b86108a3366004614559565b6001600160a01b039182165f908152600b6020908152604080832093909416825291909152205490565b6103ec6108db366004614585565b61207c565b6103ec6108ee3660046145bf565b6120cf565b6103ec6109013660046145bf565b612112565b6103ec6109143660046145fd565b612126565b6103ec610927366004614155565b612266565b6104b861093a3660046141a6565b6122dc565b6104b861234b565b6103ec610955366004614155565b612359565b335f9081526018602052604090205460ff16610974575f5ffd5b604051806060016040528084848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920182905250938552505050602080830185905242604093840152878252600c905220815181906109db90826146a8565b506020820151816001015560408201518160020155905050600d5f8281526020019081526020015f20545f03610a4a57600e80546001810182557fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd01829055545f828152600d60205260409020555b837fb4c22d60cd550a815744f04e3ff5278bf19684565ee00e2b084041b6024bd6f6848484604051610a7e9392919061478a565b60405180910390a250505050565b606060058054610a9b9061462c565b80601f0160208091040260200160405190810160405280929190818152602001828054610ac79061462c565b8015610b125780601f10610ae957610100808354040283529160200191610b12565b820191905f5260205f20905b815481529060010190602001808311610af557829003601f168201915b5050505050905090565b5f6001600160a01b038316610b4c5760405162461bcd60e51b8152600401610b43906147ad565b60405180910390fd5b335f818152600b602090815260408083206001600160a01b03881680855290835292819020869055518581529192917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35060015b92915050565b335f818152601a6020908152604080832086845282528083206001600160a01b0386168085529252808320805460ff1916600117905551909185917f3646a897c70797ecc134b0adc32f471b07bf1d6f451133b0384badab531e3fd69190a45050565b5f6001600160a01b038316610c3a5760405162461bcd60e51b8152600401610b43906147ad565b5f848152601960209081526040808320338085529083528184206001600160a01b038816808652908452938290208690559051858152909187917ff061499aa77c2f6f5e25e34955a06623705344a88256cc861a121ec0bce5cfec910160405180910390a45060015b9392505050565b335f818152601a6020908152604080832086845282528083206001600160a01b0386168085529252808320805460ff1916905551909185917f3b287c4f1bab4df949b33bceacef984f544dc5d5479930d00e4ee8c9d8dd96f29190a45050565b610d126123c2565b610d4e838383808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525061241b92505050565b505050565b5f610d5c612522565b610d66338561257b565b80610d9357506001600160a01b0384165f908152600b602090815260408083203384529091529020548211155b610daf5760405162461bcd60e51b8152600401610b43906147c9565b6001600160a01b0384165f908152600b602090815260408083203384529091529020548211610e2e576001600160a01b0384165f908152600b60209081526040808320338452909152902054610e069083906147f9565b6001600160a01b0385165f908152600b60209081526040808320338452909152902055610e52565b6001600160a01b0384165f908152600b602090815260408083203384529091528120555b610e6d3385858560405180602001604052805f8152506125f7565b506001610ca36001600455565b5f8281526001602052604081205460ff1615610ed05760405173455243313832305f4143434550545f4d4147494360601b6020820152603401604051602081830303815290604052805190602001209050610baa565b505f610baa565b610edf612522565b610f213333868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506125f792505050565b610f2b6001600455565b50505050565b610f3a33611b8b565b80610f4e57505f546001600160a01b031633145b610f56575f5ffd5b610f5f81612731565b50565b610f6a612522565b610f218433338686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525060408051602081019091529081529250612772915050565b610fc333611b8b565b80610fd757505f546001600160a01b031633145b610fdf575f5ffd5b610fe7612522565b60095462010000900460ff1661100f5760405162461bcd60e51b8152600401610b439061480c565b6110518533868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061283f92505050565b61105b6001600455565b5050505050565b6060600f805480602002602001604051908101604052809291908181526020018280548015610b1257602002820191905f5260205f20905b81548152602001906001019080831161109a575050505050905090565b5f5f5f611187611103638c0dee9c60e01b5f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506128e592505050565b8c338d8d8d8d8d8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f820116905080830192505050505050508c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506129e192505050565b9250925092505b985098509895505050505050565b6111a46123c2565b6009805462ff000019169055565b5f6111be848484612ac0565b949350505050565b6111ce6123c2565b6111d75f612b46565b565b6001600160a01b0381165f9081526012602090815260409182902080548351818402810184019094528084526060939283018282801561123657602002820191905f5260205f20905b815481526020019060010190808311611222575b50505050509050919050565b60606017805480602002602001604051908101604052809291908181526020018280548015610b1257602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831161127a575050505050905090565b5f818152601b602090815260409182902080548351818402810184019094528084526060939283018282801561123657602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116112e05750505050509050919050565b6113116123c2565b6001600160a01b0384161561142f5760405163118fa5db60e01b81526001600160a01b0385169063118fa5db9061135990309086906001908190819081908a90600401614828565b5f604051808303815f87803b158015611370575f5ffd5b505af1158015611382573d5f5f3e3d5ffd5b505050506001600160a01b038316156113f25760405163c69664bb60e01b81523060048201526001600160a01b03848116602483015285169063c69664bb906044015f604051808303815f87803b1580156113db575f5ffd5b505af11580156113ed573d5f5f3e3d5ffd5b505050505b61142f846040518060400160405280601681526020017522a921989a18182a37b5b2b739ab30b634b230ba37b960511b8152506001806001612b95565b610f2b81612c4e565b5f61144489338a612ac0565b8061147857505f8981526019602090815260408083206001600160a01b038c16845282528083203384529091529020548611155b6114945760405162461bcd60e51b8152600401610b43906147c9565b5f8981526019602090815260408083206001600160a01b038c16845282528083203384529091529020548611611528575f8981526019602090815260408083206001600160a01b038c16845282528083203384529091529020546114f99087906147f9565b5f8a81526019602090815260408083206001600160a01b038d1684528252808320338452909152902055611553565b5f8981526019602090815260408083206001600160a01b038c16845282528083203384529091528120555b6115c989338a8a8a8a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b90819084018382808284375f92019190915250612d1c92505050565b9998505050505050505050565b5f5f5f61167061162263f3d490db60e01b5f368080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506128e592505050565b8933338b8b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920182905250604080516020810190915290815292506129e1915050565b925092509250955095509592505050565b6116896123c2565b6116938282612e73565b5050565b336001600160a01b038216036116ab575f5ffd5b6001600160a01b0381165f818152601660209081526040808320338085529252808320805460ff19166001179055519092917ff4caeb2d6ca8932a215a353d0703c326ec2d81fc68170f320eb2ab49e9df61f991a350565b606060068054610a9b9061462c565b61171a612522565b611724338561257b565b8061175157506001600160a01b0384165f908152600b602090815260408083203384529091529020548311155b61176d5760405162461bcd60e51b8152600401610b43906147c9565b6001600160a01b0384165f908152600b6020908152604080832033845290915290205483116117ec576001600160a01b0384165f908152600b602090815260408083203384529091529020546117c49084906147f9565b6001600160a01b0385165f908152600b60209081526040808320338452909152902055611810565b6001600160a01b0384165f908152600b602090815260408083203384529091528120555b610f2133858585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612ee492505050565b61185a33611b8b565b8061186e57505f546001600160a01b031633145b611876575f5ffd5b610f5f8161300a565b6111d733612731565b611890612522565b61189b853386612ac0565b806118cf57505f8581526019602090815260408083206001600160a01b038816845282528083203384529091529020548311155b6119005760405162461bcd60e51b815260206004820152600260248201526106a760f31b6044820152606401610b43565b5f8581526019602090815260408083206001600160a01b038816845282528083203384529091529020548311611994575f8581526019602090815260408083206001600160a01b038816845282528083203384529091529020546119659084906147f9565b5f8681526019602090815260408083206001600160a01b038916845282528083203384529091529020556119bf565b5f8581526019602090815260408083206001600160a01b038816845282528083203384529091528120555b6110518533868660405180602001604052805f81525087878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061277292505050565b6060600e805480602002602001604051908101604052809291908181526020018280548015610b1257602002820191905f5260205f209081548152602001906001019080831161109a575050505050905090565b611a6c6123c2565b611ab08686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250889250879150869050612b95565b505050505050565b5f46817f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f611ae4610a8c565b80519060200120611b096040805180820190915260018152603160f81b602082015290565b80516020918201206040805192830194909452928101919091526060810191909152608081018390523060a082015260c00160408051601f1981840301815291905280516020909101209392505050565b5f611b63612522565b611b7e3333858560405180602001604052805f8152506125f7565b506001610baa6001600455565b5f610baa60028361304b565b5f818152600c602052604081208054606092918291611bb59061462c565b90505f03611bc1575f5ffd5b5f848152600c602052604090206001810154600282015482548390611be59061462c565b80601f0160208091040260200160405190810160405280929190818152602001828054611c119061462c565b8015611c5c5780601f10611c3357610100808354040283529160200191611c5c565b820191905f5260205f20905b815481529060010190602001808311611c3f57829003601f168201915b505050505092509250925092509193909250565b5f610ca3838361257b565b611c8433611b8b565b80611c9857505f546001600160a01b031633145b611ca0575f5ffd5b611ca8612522565b60095462010000900460ff16611cd05760405162461bcd60e51b8152600401610b439061480c565b6015545f03611cf15760405162461bcd60e51b8152600401610b439061480c565b610f2160155f81548110611d0757611d0761488b565b905f5260205f20015433868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061283f92505050565b60606015805480602002602001604051908101604052809291908181526020018280548015610b1257602002820191905f5260205f209081548152602001906001019080831161109a575050505050905090565b335f9081526018602052604090205460ff16611def5760405162461bcd60e51b815260206004820152600c60248201526b155b985d5d1a1bdc9a5e995960a21b6044820152606401610b43565b5f818152600c602052604090208054611e079061462c565b90505f03611e4f5760405162461bcd60e51b8152602060048201526015602482015274111bd8dd5b595b9d08191bd95cdb9d08195e1a5cdd605a1b6044820152606401610b43565b5f818152600c6020526040808220815160608101909252805482908290611e759061462c565b80601f0160208091040260200160405190810160405280929190818152602001828054611ea19061462c565b8015611eec5780601f10611ec357610100808354040283529160200191611eec565b820191905f5260205f20905b815481529060010190602001808311611ecf57829003601f168201915b505050505081526020016001820154815260200160028201548152505090505f600d5f836020015181526020019081526020015f205490505f8111611f635760405162461bcd60e51b815260206004820152600d60248201526c092dcecc2d8d2c840d2dcc8caf609b1b6044820152606401610b43565b600e80545f9190611f76906001906147f9565b81548110611f8657611f8661488b565b905f5260205f200154905080600e600184611fa191906147f9565b81548110611fb157611fb161488b565b5f918252602080832090910192909255828152600d90915260409020829055600e805480611fe157611fe161489f565b5f828152602080822083015f19908101839055909201909255848101518252600d81526040808320839055868352600c9091528120906120218282613da1565b505f600182018190556002909101558251602084015160405186927f3d9bba27d3e360d8c80645beed7e991454a8271bf6f269a24f7782be0f0d065492610a7e926148b3565b61206f6123c2565b6009805461ff0019169055565b612084612522565b6120c533338585858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250612ee492505050565b610d4e6001600455565b6120d76123c2565b6116938282808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250612c4e92505050565b61211a6123c2565b610d4e60158383613dd8565b61212e612522565b612138338661257b565b8061216557506001600160a01b0385165f908152600b602090815260408083203384529091529020548311155b6121815760405162461bcd60e51b8152600401610b43906147c9565b6001600160a01b0385165f908152600b602090815260408083203384529091529020548311612200576001600160a01b0385165f908152600b602090815260408083203384529091529020546121d89084906147f9565b6001600160a01b0386165f908152600b60209081526040808320338452909152902055612224565b6001600160a01b0385165f908152600b602090815260408083203384529091528120555b6110513386868686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152506125f792505050565b61226e6123c2565b6001600160a01b0381166122d35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610b43565b610f5f81612b46565b5f6122e5612522565b612336863333888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525060408051602081019091529081529250612d1c915050565b90506123426001600455565b95945050505050565b5f6123546130cc565b905090565b336001600160a01b0382160361236d575f5ffd5b6001600160a01b0381165f818152601660209081526040808320338085529252808320805460ff19169055519092917f50546e66e5f44d728365dc3908c63bc5cfeeab470722c1677e3073a6ac294aa191a350565b5f546001600160a01b031633146111d75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610b43565b5f5b5f838152601b6020526040902054811015612499575f838152601c60209081526040808320601b909252822080548391908590811061245e5761245e61488b565b5f918252602080832091909101546001600160a01b031683528201929092526040019020805460ff191691151591909117905560010161241d565b505f5b8151811015612503575f838152601c602052604081208351600192908590859081106124ca576124ca61488b565b6020908102919091018101516001600160a01b031682528101919091526040015f20805460ff191691151591909117905560010161249c565b505f828152601b602090815260409091208251610d4e92840190613e21565b6002600454036125745760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610b43565b6002600455565b5f816001600160a01b0316836001600160a01b031614806125c057506001600160a01b038084165f9081526016602090815260408083209386168352929052205460ff165b80610ca35750600954610100900460ff168015610ca3575050506001600160a01b03165f9081526018602052604090205460ff1690565b6015545f036126185760405162461bcd60e51b8152600401610b439061480c565b815f805b601554811015612709576001600160a01b0387165f90815260146020526040812060158054919291849081106126545761265461488b565b905f5260205f20015481526020019081526020015f205491508183116126b5576126ac6015828154811061268a5761268a61488b565b905f5260205f200154898989878960405180602001604052805f815250612d1c565b505f9250612709565b8115612701576126f3601582815481106126d1576126d161488b565b905f5260205f200154898989868960405180602001604052805f815250612d1c565b506126fe82846147f9565b92505b60010161261c565b5081156127285760405162461bcd60e51b8152600401610b43906148d4565b50505050505050565b61273c6002826130f4565b6040516001600160a01b038216907fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb66692905f90a250565b6001600160a01b0384165f9081526014602090815260408083208984529091529020548311156127b45760405162461bcd60e51b8152600401610b43906148d4565b6127c38686865f878787613175565b6127d28686865f878787613230565b6127dd8487856132b6565b6127e985858585613569565b836001600160a01b0316856001600160a01b0316877fce306c3dbc4a497124b5a4f2be8388b41084c1d74663da27ecee1186c00239bf868560405161282f9291906148f0565b60405180910390a4505050505050565b61285c85855f86868660405180602001604052805f815250613230565b612868848484846136f1565b612873838684613840565b61289085855f86868660405180602001604052805f81525061397f565b826001600160a01b0316846001600160a01b0316867ff0ded82afbb1bb3ff3fc48cb2a26584aa84e4af0bf309c804ecdb94d0f6a98bb85856040516128d6929190614908565b60405180910390a45050505050565b60605f82516001600160401b038111156129015761290161435c565b6040519080825280601f01601f19166020018201604052801561292b576020820181803683370190505b5090505f5b600481101561297f5784816004811061294b5761294b61488b565b1a60f81b8282815181106129615761296161488b565b60200101906001600160f81b03191690815f1a905350600101612930565b5060045b83518110156129d95783818151811061299e5761299e61488b565b602001015160f81c60f81b8282815181106129bb576129bb61488b565b60200101906001600160f81b03191690815f1a905350600101612983565b509392505050565b5f5f5f5f612a1b306040518060400160405280601481526020017322a921989a18182a37b5b2b739a1b432b1b5b2b960611b815250613a05565b90506001600160a01b03811615612ab15760405163c71ff52760e01b81526001600160a01b0382169063c71ff52790612a66908f908f908f908f908f908f908f908f90600401614939565b606060405180830381865afa158015612a81573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612aa591906149af565b9350935093505061118e565b505f925082915089905061118e565b5f612acb838361257b565b80612b0257506001600160a01b038083165f908152601a6020908152604080832088845282528083209387168352929052205460ff165b806111be5750600954610100900460ff1680156111be575050505f918252601c602090815260408084206001600160a01b0393909316845291905290205460ff1690565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f612ba03086613a05565b90506001600160a01b03811615801590612bb75750835b15612bf357612bc581611b8b565b15612bd357612bd381612731565b6001600160a01b0381165f908152601860205260409020805460ff191690555b612bfd8587613ab1565b828015612c105750612c0e86611b8b565b155b15612c1e57612c1e8661300a565b8115611ab0576001600160a01b0386165f908152601860205260409020805460ff19166001179055505050505050565b5f5b601754811015612cac575f60185f60178481548110612c7157612c7161488b565b5f918252602080832091909101546001600160a01b031683528201929092526040019020805460ff1916911515919091179055600101612c50565b505f5b8151811015612d0857600160185f848481518110612ccf57612ccf61488b565b6020908102919091018101516001600160a01b031682528101919091526040015f20805460ff1916911515919091179055600101612caf565b508051611693906017906020840190613e21565b6001600160a01b0385165f9081526014602090815260408083208a8452909152812054841115612d5e5760405162461bcd60e51b8152600401610b43906148d4565b8151889015801590612d7257506040845110155b15612d8457612d818985613b4c565b90505b612d9389898989898989613175565b612da289898989898989613230565b612dad878a876132b6565b612db8878787613b76565b612dc3868287613840565b612dd28189898989898961397f565b856001600160a01b0316876001600160a01b03168a7fff4e9a26af4eb73b8bacfaa4abd4fea03d9448e7b912dc5ff4019048875aa2d48b898989604051612e1c94939291906149ef565b60405180910390a4888114612e675780897f67c8ba31d2dd11f1384577b3405b04ed91eed1231e408432ad2458cab37b2fa187604051612e5e91815260200190565b60405180910390a35b98975050505050505050565b612e9f6040518060400160405280600a81526020016922a92199182a37b5b2b760b11b81525083613ab1565b612ecd6040518060400160405280600c81526020016b22a921989a18182a37b5b2b760a11b81525083613ab1565b8015611693576009805460ff191660011790555050565b6015545f03612f055760405162461bcd60e51b8152600401610b439061480c565b815f805b601554811015612feb576001600160a01b0386165f9081526014602052604081206015805491929184908110612f4157612f4161488b565b905f5260205f20015481526020019081526020015f20549150818311612fa057612f9860158281548110612f7757612f7761488b565b905f5260205f2001548888868860405180602001604052805f815250612772565b5f9250612feb565b612fd760158281548110612fb657612fb661488b565b905f5260205f2001548888858860405180602001604052805f815250612772565b612fe182846147f9565b9250600101612f09565b508115611ab05760405162461bcd60e51b8152600401610b43906148d4565b613015600282613ce2565b6040516001600160a01b038216907f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6905f90a250565b5f6001600160a01b0382166130ad5760405162461bcd60e51b815260206004820152602260248201527f526f6c65733a206163636f756e7420697320746865207a65726f206164647265604482015261737360f01b6064820152608401610b43565b506001600160a01b03165f908152602091909152604090205460ff1690565b465f9081526003602052604081205480156130e657919050565b6130ee613d5d565b91505090565b6130fe828261304b565b6131545760405162461bcd60e51b815260206004820152602160248201527f526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c6044820152606560f81b6064820152608401610b43565b6001600160a01b03165f90815260209190915260409020805460ff19169055565b5f6131ab866040518060400160405280601381526020017222a921989a18182a37b5b2b739a9b2b73232b960691b815250613a05565b90506001600160a01b038116156132265760405163139d569560e21b81526001600160a01b03821690634e755a54906131f8905f9036908d908d908d908d908d908d908d90600401614a32565b5f604051808303815f87803b15801561320f575f5ffd5b505af1158015613221573d5f5f3e3d5ffd5b505050505b5050505050505050565b5f613269306040518060400160405280601681526020017522a921989a18182a37b5b2b739ab30b634b230ba37b960511b815250613a05565b90506001600160a01b0381161561322657604051632907d53b60e11b81526001600160a01b0382169063520faa76906131f8905f9036908d908d908d908d908d908d908d90600401614a32565b6001600160a01b0383165f9081526014602090815260408083208584529091529020546132e49082906147f9565b6001600160a01b0384165f90815260146020908152604080832086845282528083209390935560119052205461331b9082906147f9565b5f83815260116020526040812082905503613401575f828152601060205260409020548061335b5760405162461bcd60e51b8152600401610b4390614aaa565b600f80545f919061336e906001906147f9565b8154811061337e5761337e61488b565b905f5260205f200154905080600f60018461339991906147f9565b815481106133a9576133a961488b565b5f918252602080832090910192909255828152601090915260409020829055600f8054806133d9576133d961489f565b5f828152602080822083015f1990810183905590920190925585825260109052604081205550505b6001600160a01b0383165f9081526014602090815260408083208584529091528120549003610d4e576001600160a01b0383165f9081526013602090815260408083208584529091529020548061346a5760405162461bcd60e51b8152600401610b4390614aaa565b6001600160a01b0384165f908152601260205260408120805461348f906001906147f9565b8154811061349f5761349f61488b565b5f9182526020808320909101546001600160a01b03881683526012909152604090912090915081906134d26001856147f9565b815481106134e2576134e261488b565b5f9182526020808320909101929092556001600160a01b038716808252601383526040808320858452845280832086905590825260129092522080548061352b5761352b61489f565b5f828152602080822083015f199081018390559092019092556001600160a01b03871682526013815260408083208784529091528120555050505050565b60095460ff161561358c5760405162461bcd60e51b8152600401610b4390614ac6565b61359582613d7f565b6135b15760405162461bcd60e51b8152600401610b4390614aaa565b6001600160a01b0383166135d75760405162461bcd60e51b8152600401610b43906147ad565b6001600160a01b0383165f908152600a602052604090205482111561360e5760405162461bcd60e51b8152600401610b43906148d4565b6001600160a01b0383165f908152600a60205260409020546136319083906147f9565b6001600160a01b0384165f908152600a60205260409020556008546136579083906147f9565b600881905550826001600160a01b0316846001600160a01b03167fb7d0d6b60740753e9f16692a2f479472a1385aec2420fa43225b02f2ffa1afe784846040516136a29291906148f0565b60405180910390a36040518281525f906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a350505050565b60095460ff16156137145760405162461bcd60e51b8152600401610b4390614ac6565b61371d82613d7f565b6137395760405162461bcd60e51b8152600401610b4390614aaa565b6001600160a01b0383166137745760405162461bcd60e51b8152602060048201526002602482015261353760f01b6044820152606401610b43565b816008546137829190614ae2565b6008556001600160a01b0383165f908152600a60205260409020546137a8908390614ae2565b6001600160a01b038085165f818152600a602052604090819020939093559151908616907f0e9905d62635f049c2f4e11678ebf9dc3d1f8c4a653e290759b772e47ba00d00906137fb90869086906148f0565b60405180910390a36040518281526001600160a01b038416905f907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016136e3565b8015610d4e576001600160a01b0383165f90815260136020908152604080832085845290915281205490036138b2576001600160a01b0383165f818152601260209081526040808320805460018101825581855283852001879055938352925460138252838320868452909152919020555b6001600160a01b0383165f9081526014602090815260408083208584529091529020546138e0908290614ae2565b6001600160a01b0384165f9081526014602090815260408083208684528252808320939093556010905290812054900361395357600f80546001810182557f8d1108e10bcb7c27dddfc02ed9d693a074039d026cf4ea4240b40f7d581ac80201839055545f838152601060205260409020555b5f8281526011602052604090205461396c908290614ae2565b5f83815260116020526040902055505050565b5f6139b88560405180604001604052806016815260200175115490cc4d0c0c151bdad95b9cd49958da5c1a595b9d60521b815250613a05565b90506001600160a01b0381161561322657604051637a325abb60e11b81526001600160a01b0382169063f464b576906131f8905f9036908d908d908d908d908d908d908d90600401614a32565b5f5f82604051602001613a189190614af5565b60408051808303601f1901815290829052805160209091012063555ddc6560e11b82526001600160a01b0386166004830152602482018190529150731820a4b7618bde71dce8cdc73aab6c95905fad249063aabbb8ca90604401602060405180830381865afa158015613a8d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111be9190614b0b565b5f82604051602001613ac39190614af5565b60408051808303601f190181529082905280516020909101206329965a1d60e01b8252306004830152602482018190526001600160a01b03841660448301529150731820a4b7618bde71dce8cdc73aab6c95905fad24906329965a1d906064015f604051808303815f87803b158015613b3a575f5ffd5b505af1158015612728573d5f5f3e3d5ffd5b60208101515f905f199060018101613b6a5760408401519250613b6e565b8492505b505092915050565b60095460ff1615613b995760405162461bcd60e51b8152600401610b4390614ac6565b613ba281613d7f565b613bbe5760405162461bcd60e51b8152600401610b4390614aaa565b6001600160a01b038216613bf95760405162461bcd60e51b8152602060048201526002602482015261353760f01b6044820152606401610b43565b6001600160a01b0383165f908152600a6020526040902054811115613c305760405162461bcd60e51b8152600401610b43906148d4565b6001600160a01b0383165f908152600a6020526040902054613c539082906147f9565b6001600160a01b038085165f908152600a60205260408082209390935590841681522054613c82908290614ae2565b6001600160a01b038084165f818152600a602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90613cd59085815260200190565b60405180910390a3505050565b613cec828261304b565b15613d395760405162461bcd60e51b815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c65006044820152606401610b43565b6001600160a01b03165f90815260209190915260409020805460ff19166001179055565b5f4681613d68611ab8565b5f9283526003602052604090922082905550919050565b6007545f908290613d908183614b26565b613d9a9190614b45565b1492915050565b508054613dad9061462c565b5f825580601f10613dbc575050565b601f0160209004905f5260205f2090810190610f5f9190613e74565b828054828255905f5260205f20908101928215613e11579160200282015b82811115613e11578235825591602001919060010190613df6565b50613e1d929150613e74565b5090565b828054828255905f5260205f20908101928215613e11579160200282015b82811115613e1157825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190613e3f565b5b80821115613e1d575f8155600101613e75565b5f5f83601f840112613e98575f5ffd5b5081356001600160401b03811115613eae575f5ffd5b602083019150836020828501011115613ec5575f5ffd5b9250929050565b5f5f5f5f60608587031215613edf575f5ffd5b8435935060208501356001600160401b03811115613efb575f5ffd5b613f0787828801613e88565b9598909750949560400135949350505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f610ca36020830184613f1a565b6001600160a01b0381168114610f5f575f5ffd5b8035613f7981613f5a565b919050565b5f5f60408385031215613f8f575f5ffd5b8235613f9a81613f5a565b946020939093013593505050565b5f5f60408385031215613fb9575f5ffd5b823591506020830135613fcb81613f5a565b809150509250929050565b5f5f5f60608486031215613fe8575f5ffd5b833592506020840135613ffa81613f5a565b929592945050506040919091013590565b5f5f83601f84011261401b575f5ffd5b5081356001600160401b03811115614031575f5ffd5b6020830191508360208260051b8501011115613ec5575f5ffd5b5f5f5f6040848603121561405d575f5ffd5b8335925060208401356001600160401b03811115614079575f5ffd5b6140858682870161400b565b9497909650939450505050565b5f5f5f606084860312156140a4575f5ffd5b8335925060208401356140b681613f5a565b915060408401356140c681613f5a565b809150509250925092565b5f5f5f606084860312156140e3575f5ffd5b83356140ee81613f5a565b92506020840135613ffa81613f5a565b5f5f5f5f60608587031215614111575f5ffd5b843561411c81613f5a565b93506020850135925060408501356001600160401b0381111561413d575f5ffd5b61414987828801613e88565b95989497509550505050565b5f60208284031215614165575f5ffd5b8135610ca381613f5a565b5f5f5f5f60608587031215614183575f5ffd5b843593506020850135925060408501356001600160401b0381111561413d575f5ffd5b5f5f5f5f5f608086880312156141ba575f5ffd5b8535945060208601356141cc81613f5a565b93506040860135925060608601356001600160401b038111156141ed575f5ffd5b6141f988828901613e88565b969995985093965092949392505050565b602080825282518282018190525f918401906040840190835b81811015614241578351835260209384019390920191600101614223565b509095945050505050565b5f5f5f5f5f5f5f5f60c0898b031215614263575f5ffd5b88359750602089013561427581613f5a565b9650604089013561428581613f5a565b95506060890135945060808901356001600160401b038111156142a6575f5ffd5b6142b28b828c01613e88565b90955093505060a08901356001600160401b038111156142d0575f5ffd5b6142dc8b828c01613e88565b999c989b5096995094979396929594505050565b5f8151808452602084019350602083015f5b828110156143295781516001600160a01b0316865260209586019590910190600101614302565b5093949350505050565b602081525f610ca360208301846142f0565b5f60208284031215614355575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f5f60808587031215614383575f5ffd5b843561438e81613f5a565b9350602085013561439e81613f5a565b92506040850135600381106143b1575f5ffd5b915060608501356001600160401b038111156143cb575f5ffd5b8501601f810187136143db575f5ffd5b80356001600160401b038111156143f4576143f461435c565b8060051b604051601f19603f83011681018181106001600160401b03821117156144205761442061435c565b60405291825260208184018101929081018a84111561443d575f5ffd5b6020850194505b838510156144635761445585613f6e565b815260209485019401614444565b50969995985093965050505050565b80358015158114613f79575f5ffd5b5f5f60408385031215614492575f5ffd5b823561449d81613f5a565b91506144ab60208401614472565b90509250929050565b5f5f5f5f5f5f60a087890312156144c9575f5ffd5b86356144d481613f5a565b955060208701356001600160401b038111156144ee575f5ffd5b6144fa89828a01613e88565b909650945061450d905060408801614472565b925061451b60608801614472565b915061452960808801614472565b90509295509295509295565b606081525f6145476060830186613f1a565b60208301949094525060400152919050565b5f5f6040838503121561456a575f5ffd5b823561457581613f5a565b91506020830135613fcb81613f5a565b5f5f5f60408486031215614597575f5ffd5b8335925060208401356001600160401b038111156145b3575f5ffd5b61408586828701613e88565b5f5f602083850312156145d0575f5ffd5b82356001600160401b038111156145e5575f5ffd5b6145f18582860161400b565b90969095509350505050565b5f5f5f5f5f60808688031215614611575f5ffd5b853561461c81613f5a565b945060208601356141cc81613f5a565b600181811c9082168061464057607f821691505b60208210810361465e57634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115610d4e57805f5260205f20601f840160051c810160208510156146895750805b601f840160051c820191505b8181101561105b575f8155600101614695565b81516001600160401b038111156146c1576146c161435c565b6146d5816146cf845461462c565b84614664565b6020601f821160018114614707575f83156146f05750848201515b5f19600385901b1c1916600184901b17845561105b565b5f84815260208120601f198516915b828110156147365787850151825560209485019460019092019101614716565b508482101561475357868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f61479d604083018587614762565b9050826020830152949350505050565b6020808252600290820152611a9b60f11b604082015260600190565b602080825260029082015261353360f01b604082015260600190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610baa57610baa6147e5565b602080825260029082015261353560f01b604082015260600190565b6001600160a01b03881681525f6003881061485157634e487b7160e01b5f52602160045260245ffd5b87602083015286151560408301528515156060830152841515608083015283151560a083015260e060c08301526115c960e08301846142f0565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b604081525f6148c56040830185613f1a565b90508260208301529392505050565b6020808252600290820152611a9960f11b604082015260600190565b828152604060208201525f6111be6040830184613f1a565b828152606060208201525f6149206060830184613f1a565b82810360408401525f8152602081019150509392505050565b61010081525f61494d61010083018b613f1a565b602083018a90526001600160a01b03898116604085015288811660608501528716608084015260a0830186905282810360c084015261498c8186613f1a565b905082810360e08401526149a08185613f1a565b9b9a5050505050505050505050565b5f5f5f606084860312156149c1575f5ffd5b83516001600160f81b0319811681146149d8575f5ffd5b602085015160409095015190969495509392505050565b60018060a01b0385168152836020820152608060408201525f614a156080830185613f1a565b8281036060840152614a278185613f1a565b979650505050505050565b61010081525f614a4761010083018b8d614762565b602083018a90526001600160a01b03898116604085015288811660608501528716608084015260a0830186905282810360c0840152614a868186613f1a565b905082810360e0840152614a9a8185613f1a565b9c9b505050505050505050505050565b602080825260029082015261035360f41b604082015260600190565b6020808252600290820152610d4d60f21b604082015260600190565b80820180821115610baa57610baa6147e5565b5f82518060208501845e5f920191825250919050565b5f60208284031215614b1b575f5ffd5b8151610ca381613f5a565b5f82614b4057634e487b7160e01b5f52601260045260245ffd5b500490565b8082028115828204841417610baa57610baa6147e556fea2646970667358221220125db6e31d606a4a1b7374038be2b1bd55372a45cfefa37cf02e0d2034f1664a64736f6c634300081e0033
Verified Source Code Partial Match
Compiler: v0.8.30+commit.73712a01
EVM: prague
Optimization: Yes (200 runs)
NSDQ.sol 2368 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
abstract contract DomainAware {
// Mapping of ChainID to domain separators. This is a very gas efficient way
// to not recalculate the domain separator on every call, while still
// automatically detecting ChainID changes.
mapping(uint256 => bytes32) private domainSeparators;
constructor() {
_updateDomainSeparator();
}
function domainName() public virtual view returns (string memory);
function domainVersion() public virtual view returns (string memory);
function generateDomainSeparator() public view returns (bytes32) {
uint256 chainID = _chainID();
// no need for assembly, running very rarely
bytes32 domainSeparatorHash = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(domainName())), // ERC-20 Name
keccak256(bytes(domainVersion())), // Version
chainID,
address(this)
)
);
return domainSeparatorHash;
}
function domainSeparator() external returns (bytes32) {
return _domainSeparator();
}
function _updateDomainSeparator() private returns (bytes32) {
uint256 chainID = _chainID();
bytes32 newDomainSeparator = generateDomainSeparator();
domainSeparators[chainID] = newDomainSeparator;
return newDomainSeparator;
}
// Returns the domain separator, updating it if chainID changes
function _domainSeparator() private returns (bytes32) {
bytes32 currentDomainSeparator = domainSeparators[_chainID()];
if (currentDomainSeparator != 0x00) {
return currentDomainSeparator;
}
return _updateDomainSeparator();
}
function _chainID() internal view returns (uint256) {
uint256 chainID;
assembly {
chainID := chainid()
}
return chainID;
}
}
/**
* @title IERC1400TokensRecipient
* @dev ERC1400TokensRecipient interface
*/
interface IERC1400TokensRecipient {
function canReceive(
bytes calldata payload,
bytes32 partition,
address operator,
address from,
address to,
uint value,
bytes calldata data,
bytes calldata operatorData
) external view returns(bool);
function tokensReceived(
bytes calldata payload,
bytes32 partition,
address operator,
address from,
address to,
uint value,
bytes calldata data,
bytes calldata operatorData
) external;
}
/**
* @title IERC1400TokensSender
* @dev ERC1400TokensSender interface
*/
interface IERC1400TokensSender {
function canTransfer(
bytes calldata payload,
bytes32 partition,
address operator,
address from,
address to,
uint value,
bytes calldata data,
bytes calldata operatorData
) external view returns(bool);
function tokensToTransfer(
bytes calldata payload,
bytes32 partition,
address operator,
address from,
address to,
uint value,
bytes calldata data,
bytes calldata operatorData
) external;
}
/**
* @title IERC1400TokensChecker
* @dev IERC1400TokensChecker interface
*/
interface IERC1400TokensChecker {
// function canTransfer(
// bytes calldata payload,
// address operator,
// address from,
// address to,
// uint256 value,
// bytes calldata data,
// bytes calldata operatorData
// ) external view returns (byte, bytes32);
function canTransferByPartition(
bytes calldata payload,
bytes32 partition,
address operator,
address from,
address to,
uint256 value,
bytes calldata data,
bytes calldata operatorData
) external view returns (bytes1, bytes32, bytes32);
}
/**
* @title IERC1400TokensValidator
* @dev ERC1400TokensValidator interface
*/
interface IERC1400TokensValidator {
/**
* @dev Verify if a token transfer can be executed or not, on the validator's perspective.
* @param token Token address.
* @param payload Payload of the initial transaction.
* @param partition Name of the partition (left empty for ERC20 transfer).
* @param operator Address which triggered the balance decrease (through transfer or redemption).
* @param from Token holder.
* @param to Token recipient for a transfer and 0x for a redemption.
* @param value Number of tokens the token holder balance is decreased by.
* @param data Extra information.
* @param operatorData Extra information, attached by the operator (if any).
* @return 'true' if the token transfer can be validated, 'false' if not.
*/
struct ValidateData {
address token;
bytes payload;
bytes32 partition;
address operator;
address from;
address to;
uint value;
bytes data;
bytes operatorData;
}
function canValidate(ValidateData calldata data) external view returns(bool);
function tokensToValidate(
bytes calldata payload,
bytes32 partition,
address operator,
address from,
address to,
uint value,
bytes calldata data,
bytes calldata operatorData
) external;
}
/**
* @title Roles
* @dev Library for managing addresses assigned to a Role.
*/
library Roles {
struct Role {
mapping (address => bool) bearer;
}
/**
* @dev Give an account access to this role.
*/
function add(Role storage role, address account) internal {
require(!has(role, account), "Roles: account already has role");
role.bearer[account] = true;
}
/**
* @dev Remove an account's access to this role.
*/
function remove(Role storage role, address account) internal {
require(has(role, account), "Roles: account does not have role");
role.bearer[account] = false;
}
/**
* @dev Check if an account has this role.
* @return bool
*/
function has(Role storage role, address account) internal view returns (bool) {
require(account != address(0), "Roles: account is the zero address");
return role.bearer[account];
}
}
/**
* @title MinterRole
* @dev Minters are responsible for minting new tokens.
*/
contract MinterRole {
using Roles for Roles.Role;
event MinterAdded(address indexed account);
event MinterRemoved(address indexed account);
Roles.Role private _minters;
constructor() {
_addMinter(msg.sender);
}
modifier onlyMinter() virtual {
require(isMinter(msg.sender));
_;
}
function isMinter(address account) public view returns (bool) {
return _minters.has(account);
}
function addMinter(address account) external onlyMinter {
_addMinter(account);
}
function removeMinter(address account) external onlyMinter {
_removeMinter(account);
}
function renounceMinter() external {
_removeMinter(msg.sender);
}
function _addMinter(address account) internal {
_minters.add(account);
emit MinterAdded(account);
}
function _removeMinter(address account) internal {
_minters.remove(account);
emit MinterRemoved(account);
}
}
contract ERC1820Implementer {
bytes32 constant ERC1820_ACCEPT_MAGIC = keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"));
mapping(bytes32 => bool) internal _interfaceHashes;
function canImplementInterfaceForAddress(bytes32 interfaceHash, address /*addr*/) // Comments to avoid compilation warnings for unused variables.
external
view
returns(bytes32)
{
if(_interfaceHashes[interfaceHash]) {
return ERC1820_ACCEPT_MAGIC;
} else {
return "";
}
}
function _setInterface(string memory interfaceLabel) internal {
_interfaceHashes[keccak256(abi.encodePacked(interfaceLabel))] = true;
}
}
interface IERC1820Registry {
event InterfaceImplementerSet(address indexed account, bytes32 indexed interfaceHash, address indexed implementer);
event ManagerChanged(address indexed account, address indexed newManager);
/**
* @dev Sets `newManager` as the manager for `account`. A manager of an
* account is able to set interface implementers for it.
*
* By default, each account is its own manager. Passing a value of `0x0` in
* `newManager` will reset the manager to this initial state.
*
* Emits a {ManagerChanged} event.
*
* Requirements:
*
* - the caller must be the current manager for `account`.
*/
function setManager(address account, address newManager) external;
/**
* @dev Returns the manager for `account`.
*
* See {setManager}.
*/
function getManager(address account) external view returns (address);
/**
* @dev Sets the `implementer` contract as ``account``'s implementer for
* `interfaceHash`.
*
* `account` being the zero address is an alias for the caller's address.
* The zero address can also be used in `implementer` to remove an old one.
*
* See {interfaceHash} to learn how these are created.
*
* Emits an {InterfaceImplementerSet} event.
*
* Requirements:
*
* - the caller must be the current manager for `account`.
* - `interfaceHash` must not be an {IERC165} interface id (i.e. it must not
* end in 28 zeroes).
* - `implementer` must implement {IERC1820Implementer} and return true when
* queried for support, unless `implementer` is the caller. See
* {IERC1820Implementer-canImplementInterfaceForAddress}.
*/
function setInterfaceImplementer(
address account,
bytes32 _interfaceHash,
address implementer
) external;
/**
* @dev Returns the implementer of `interfaceHash` for `account`. If no such
* implementer is registered, returns the zero address.
*
* If `interfaceHash` is an {IERC165} interface id (i.e. it ends with 28
* zeroes), `account` will be queried for support of it.
*
* `account` being the zero address is an alias for the caller's address.
*/
function getInterfaceImplementer(address account, bytes32 _interfaceHash) external view returns (address);
/**
* @dev Returns the interface hash for an `interfaceName`, as defined in the
* corresponding
* https://eips.ethereum.org/EIPS/eip-1820#interface-name[section of the EIP].
*/
function interfaceHash(string calldata interfaceName) external pure returns (bytes32);
/**
* @notice Updates the cache with whether the contract implements an ERC165 interface or not.
* @param account Address of the contract for which to update the cache.
* @param interfaceId ERC165 interface for which to update the cache.
*/
function updateERC165Cache(address account, bytes4 interfaceId) external;
/**
* @notice Checks whether a contract implements an ERC165 interface or not.
* If the result is not cached a direct lookup on the contract address is performed.
* If the result is not cached or the cached value is out-of-date, the cache MUST be updated manually by calling
* {updateERC165Cache} with the contract address.
* @param account Address of the contract to check.
* @param interfaceId ERC165 interface to check.
* @return True if `account` implements `interfaceId`, false otherwise.
*/
function implementsERC165Interface(address account, bytes4 interfaceId) external view returns (bool);
/**
* @notice Checks whether a contract implements an ERC165 interface or not without using nor updating the cache.
* @param account Address of the contract to check.
* @param interfaceId ERC165 interface to check.
* @return True if `account` implements `interfaceId`, false otherwise.
*/
function implementsERC165InterfaceNoCache(address account, bytes4 interfaceId) external view returns (bool);
}
contract ERC1820Client {
IERC1820Registry constant ERC1820REGISTRY = IERC1820Registry(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);
}
}
abstract contract Context {
function _msgSender() internal view returns (address) {
return msg.sender;
}
}
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() external onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
/**
* @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 from, 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);
}
/// @title IERC1643 Document Management (part of the ERC1400 Security Token Standards)
/// @dev See https://github.com/SecurityTokenStandard/EIP-Spec
interface IERC1643 {
// Document Management
function getDocument(bytes32 _name) external view returns (string memory, bytes32, uint256);
function setDocument(bytes32 _name, string memory _uri, bytes32 _documentHash) external;
function removeDocument(bytes32 _name) external;
function getAllDocuments() external view returns (bytes32[] memory);
// Document Events
event DocumentRemoved(bytes32 indexed name, string uri, bytes32 documentHash);
event DocumentUpdated(bytes32 indexed name, string uri, bytes32 documentHash);
}
/**
* @title IERC1400 security token standard
* @dev See https://github.com/SecurityTokenStandard/EIP-Spec/blob/master/eip/eip-1400.md
*/
interface IERC1400 is IERC20, IERC1643 {
// ******************* Token Information ********************
function balanceOfByPartition(bytes32 partition, address tokenHolder) external view returns (uint256);
function partitionsOf(address tokenHolder) external view returns (bytes32[] memory);
// *********************** Transfers ************************
function transferWithData(address to, uint256 value, bytes calldata data) external;
function transferFromWithData(address from, address to, uint256 value, bytes calldata data) external;
// *************** Partition Token Transfers ****************
function transferByPartition(bytes32 partition, address to, uint256 value, bytes calldata data) external returns (bytes32);
function operatorTransferByPartition(bytes32 partition, address from, address to, uint256 value, bytes calldata data, bytes calldata operatorData) external returns (bytes32);
function allowanceByPartition(bytes32 partition, address owner, address spender) external view returns (uint256);
// ****************** Controller Operation ******************
function isControllable() external view returns (bool);
// function controllerTransfer(address from, address to, uint256 value, bytes calldata data, bytes calldata operatorData) external; // removed because same action can be achieved with "operatorTransferByPartition"
// function controllerRedeem(address tokenHolder, uint256 value, bytes calldata data, bytes calldata operatorData) external; // removed because same action can be achieved with "operatorRedeemByPartition"
// ****************** Operator Management *******************
function authorizeOperator(address operator) external;
function revokeOperator(address operator) external;
function authorizeOperatorByPartition(bytes32 partition, address operator) external;
function revokeOperatorByPartition(bytes32 partition, address operator) external;
// ****************** Operator Information ******************
function isOperator(address operator, address tokenHolder) external view returns (bool);
function isOperatorForPartition(bytes32 partition, address operator, address tokenHolder) external view returns (bool);
// ********************* Token Issuance *********************
function isIssuable() external view returns (bool);
function issue(address tokenHolder, uint256 value, bytes calldata data) external;
function issueByPartition(bytes32 partition, address tokenHolder, uint256 value, bytes calldata data) external;
// ******************** Token Redemption ********************
function redeem(uint256 value, bytes calldata data) external;
function redeemFrom(address tokenHolder, uint256 value, bytes calldata data) external;
function redeemByPartition(bytes32 partition, uint256 value, bytes calldata data) external;
function operatorRedeemByPartition(bytes32 partition, address tokenHolder, uint256 value, bytes calldata operatorData) external;
event TransferByPartition(
bytes32 indexed fromPartition,
address operator,
address indexed from,
address indexed to,
uint256 value,
bytes data,
bytes operatorData
);
event ChangedPartition(
bytes32 indexed fromPartition,
bytes32 indexed toPartition,
uint256 value
);
// ******************** Operator Events *********************
event AuthorizedOperator(address indexed operator, address indexed tokenHolder);
event RevokedOperator(address indexed operator, address indexed tokenHolder);
event AuthorizedOperatorByPartition(bytes32 indexed partition, address indexed operator, address indexed tokenHolder);
event RevokedOperatorByPartition(bytes32 indexed partition, address indexed operator, address indexed tokenHolder);
// ************** Issuance / Redemption Events **************
event Issued(address indexed operator, address indexed to, uint256 value, bytes data);
event Redeemed(address indexed operator, address indexed from, uint256 value, bytes data);
event IssuedByPartition(bytes32 indexed partition, address indexed operator, address indexed to, uint256 value, bytes data, bytes operatorData);
event RedeemedByPartition(bytes32 indexed partition, address indexed operator, address indexed from, uint256 value, bytes operatorData);
}
/**
* Reason codes - ERC-1066
*
* To improve the token holder experience, canTransfer MUST return a reason byte code
* on success or failure based on the ERC-1066 application-specific status codes specified below.
* An implementation can also return arbitrary data as a bytes32 to provide additional
* information not captured by the reason code.
*
* Code Reason
* 0x50 transfer failure
* 0x51 transfer success
* 0x52 insufficient balance
* 0x53 insufficient allowance
* 0x54 transfers halted (contract paused)
* 0x55 funds locked (lockup period)
* 0x56 invalid sender
* 0x57 invalid receiver
* 0x58 invalid operator (transfer agent)
* 0x59
* 0x5a
* 0x5b
* 0x5a
* 0x5b
* 0x5c
* 0x5d
* 0x5e
* 0x5f token meta or info
*
* These codes are being discussed at: https://ethereum-magicians.org/t/erc-1066-ethereum-status-codes-esc/283/24
*/
/**
* @title ERC1400
* @dev ERC1400 logic
*/
contract ERC1400 is IERC20, IERC1400, Ownable, ERC1820Client, ERC1820Implementer, MinterRole, DomainAware, ReentrancyGuard {
// Token
string constant internal ERC1400_INTERFACE_NAME = "ERC1400Token";
string constant internal ERC20_INTERFACE_NAME = "ERC20Token";
// Token extensions
string constant internal ERC1400_TOKENS_CHECKER = "ERC1400TokensChecker";
string constant internal ERC1400_TOKENS_VALIDATOR = "ERC1400TokensValidator";
// User extensions
string constant internal ERC1400_TOKENS_SENDER = "ERC1400TokensSender";
string constant internal ERC1400_TOKENS_RECIPIENT = "ERC1400TokensRecipient";
/************************************* Token description ****************************************/
string internal _name;
string internal _symbol;
uint256 internal _granularity;
uint256 internal _totalSupply;
bool internal _migrated;
/************************************************************************************************/
/**************************************** Token behaviours **************************************/
// Indicate whether the token can still be controlled by operators or not anymore.
bool internal _isControllable;
// Indicate whether the token can still be issued by the issuer or not anymore.
bool internal _isIssuable;
/************************************************************************************************/
/********************************** ERC20 Token mappings ****************************************/
// Mapping from tokenHolder to balance.
mapping(address => uint256) internal _balances;
// Mapping from (tokenHolder, spender) to allowed value.
mapping (address => mapping (address => uint256)) internal _allowed;
/************************************************************************************************/
/**************************************** Documents *********************************************/
struct Doc {
string docURI;
bytes32 docHash;
uint256 timestamp;
}
// Mapping for documents.
mapping(bytes32 => Doc) internal _documents;
mapping(bytes32 => uint256) internal _indexOfDocHashes;
bytes32[] internal _docHashes;
/************************************************************************************************/
/*********************************** Partitions mappings ***************************************/
// List of partitions.
bytes32[] internal _totalPartitions;
// Mapping from partition to their index.
mapping (bytes32 => uint256) internal _indexOfTotalPartitions;
// Mapping from partition to global balance of corresponding partition.
mapping (bytes32 => uint256) internal _totalSupplyByPartition;
// Mapping from tokenHolder to their partitions.
mapping (address => bytes32[]) internal _partitionsOf;
// Mapping from (tokenHolder, partition) to their index.
mapping (address => mapping (bytes32 => uint256)) internal _indexOfPartitionsOf;
// Mapping from (tokenHolder, partition) to balance of corresponding partition.
mapping (address => mapping (bytes32 => uint256)) internal _balanceOfByPartition;
// List of token default partitions (for ERC20 compatibility).
bytes32[] internal _defaultPartitions;
/************************************************************************************************/
/********************************* Global operators mappings ************************************/
// Mapping from (operator, tokenHolder) to authorized status. [TOKEN-HOLDER-SPECIFIC]
mapping(address => mapping(address => bool)) internal _authorizedOperator;
// Array of controllers. [GLOBAL - NOT TOKEN-HOLDER-SPECIFIC]
address[] internal _controllers;
// Mapping from operator to controller status. [GLOBAL - NOT TOKEN-HOLDER-SPECIFIC]
mapping(address => bool) internal _isController;
/************************************************************************************************/
/******************************** Partition operators mappings **********************************/
// Mapping from (partition, tokenHolder, spender) to allowed value. [TOKEN-HOLDER-SPECIFIC]
mapping(bytes32 => mapping (address => mapping (address => uint256))) internal _allowedByPartition;
// Mapping from (tokenHolder, partition, operator) to 'approved for partition' status. [TOKEN-HOLDER-SPECIFIC]
mapping (address => mapping (bytes32 => mapping (address => bool))) internal _authorizedOperatorByPartition;
// Mapping from partition to controllers for the partition. [NOT TOKEN-HOLDER-SPECIFIC]
mapping (bytes32 => address[]) internal _controllersByPartition;
// Mapping from (partition, operator) to PartitionController status. [NOT TOKEN-HOLDER-SPECIFIC]
mapping (bytes32 => mapping (address => bool)) internal _isControllerByPartition;
/************************************************************************************************/
/***************************************** Modifiers ********************************************/
/**
* @dev Modifier to verify if token is issuable.
*/
modifier isIssuableToken() {
require(_isIssuable, "55"); // 0x55 funds locked (lockup period)
_;
}
/**
* @dev Modifier to make a function callable only when the contract is not migrated.
*/
modifier isNotMigratedToken() {
require(!_migrated, "54"); // 0x54 transfers halted (contract paused)
_;
}
/**
* @dev Modifier to verifiy if sender is a minter.
*/
modifier onlyMinter() override {
require(isMinter(msg.sender) || owner() == _msgSender());
_;
}
/************************************************************************************************/
/**************************** Events (additional - not mandatory) *******************************/
event ApprovalByPartition(bytes32 indexed partition, address indexed owner, address indexed spender, uint256 value);
/************************************************************************************************/
/**
* @dev Initialize ERC1400 + register the contract implementation in ERC1820Registry.
* @param name_ Name of the token.
* @param symbol_ Symbol of the token.
* @param granularity_ Granularity of the token.
* @param defaultPartitions_ Partitions chosen by default, when partition is
* not specified, like the case ERC20 tranfers.
*/
constructor(
string memory name_,
string memory symbol_,
uint256 granularity_,
bytes32[] memory defaultPartitions_
)
{
_name = name_;
_symbol = symbol_;
_totalSupply = 0;
require(granularity_ >= 1); // Constructor Blocked - Token granularity can not be lower than 1
_granularity = granularity_;
_defaultPartitions = defaultPartitions_;
_isControllable = true;
_isIssuable = true;
// Register contract in ERC1820 registry
ERC1820Client.setInterfaceImplementation(ERC1400_INTERFACE_NAME, address(this));
ERC1820Client.setInterfaceImplementation(ERC20_INTERFACE_NAME, address(this));
// Indicate token verifies ERC1400 and ERC20 interfaces
ERC1820Implementer._setInterface(ERC1400_INTERFACE_NAME); // For migration
ERC1820Implementer._setInterface(ERC20_INTERFACE_NAME); // For migration
}
/************************************************************************************************/
/****************************** EXTERNAL FUNCTIONS (ERC20 INTERFACE) ****************************/
/************************************************************************************************/
/**
* @dev Get the total number of issued tokens.
* @return Total supply of tokens currently in circulation.
*/
function totalSupply() external override view returns (uint256) {
return _totalSupply;
}
/**
* @dev Get the balance of the account with address 'tokenHolder'.
* @param tokenHolder Address for which the balance is returned.
* @return Amount of token held by 'tokenHolder' in the token contract.
*/
function balanceOf(address tokenHolder) external override view returns (uint256) {
return _balances[tokenHolder];
}
/**
* @dev Transfer token for a specified address.
* @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 nonReentrant returns (bool) {
_transferByDefaultPartitions(msg.sender, msg.sender, to, value, "");
return true;
}
/**
* @dev Check the value of tokens that an owner allowed to a spender.
* @param from 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 from, address spender) external override view returns (uint256) {
return _allowed[from][spender];
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of 'msg.sender'.
* @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) {
require(spender != address(0), "56"); // 0x56 invalid sender
_allowed[msg.sender][spender] = value;
emit Approval(msg.sender, spender, value);
return true;
}
/**
* @dev Transfer tokens from one address to another.
* @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 nonReentrant returns (bool) {
require( _isOperator(msg.sender, from)
|| (value <= _allowed[from][msg.sender]), "53"); // 0x53 insufficient allowance
if(_allowed[from][msg.sender] >= value) {
_allowed[from][msg.sender] = _allowed[from][msg.sender] - value;
} else {
_allowed[from][msg.sender] = 0;
}
_transferByDefaultPartitions(msg.sender, from, to, value, "");
return true;
}
/************************************************************************************************/
/****************************** EXTERNAL FUNCTIONS (ERC1400 INTERFACE) **************************/
/************************************************************************************************/
/************************************* Document Management **************************************/
/**
* @dev Access a document associated with the token.
* @param shortName Short name (represented as a bytes32) associated to the document.
* @return Requested document + document hash + document timestamp.
*/
function getDocument(bytes32 shortName) external override view returns (string memory, bytes32, uint256) {
require(bytes(_documents[shortName].docURI).length != 0); // Action Blocked - Empty document
return (
_documents[shortName].docURI,
_documents[shortName].docHash,
_documents[shortName].timestamp
);
}
/**
* @dev Associate a document with the token.
* @param shortName Short name (represented as a bytes32) associated to the document.
* @param uri Document content.
* @param documentHash Hash of the document [optional parameter].
*/
function setDocument(bytes32 shortName, string calldata uri, bytes32 documentHash) external override {
require(_isController[msg.sender]);
_documents[shortName] = Doc({
docURI: uri,
docHash: documentHash,
timestamp: block.timestamp
});
if (_indexOfDocHashes[documentHash] == 0) {
_docHashes.push(documentHash);
_indexOfDocHashes[documentHash] = _docHashes.length;
}
emit DocumentUpdated(shortName, uri, documentHash);
}
function removeDocument(bytes32 shortName) external override {
require(_isController[msg.sender], "Unauthorized");
require(bytes(_documents[shortName].docURI).length != 0, "Document doesnt exist"); // Action Blocked - Empty document
Doc memory data = _documents[shortName];
uint256 index1 = _indexOfDocHashes[data.docHash];
require(index1 > 0, "Invalid index"); //Indexing starts at 1, 0 is not allowed
// move the last item into the index being vacated
bytes32 lastValue = _docHashes[_docHashes.length - 1];
_docHashes[index1 - 1] = lastValue; // adjust for 1-based indexing
_indexOfDocHashes[lastValue] = index1;
//_totalPartitions.length -= 1;
_docHashes.pop();
_indexOfDocHashes[data.docHash] = 0;
delete _documents[shortName];
emit DocumentRemoved(shortName, data.docURI, data.docHash);
}
function getAllDocuments() external override view returns (bytes32[] memory) {
return _docHashes;
}
/************************************************************************************************/
/************************************** Token Information ***************************************/
/**
* @dev 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 override view returns (uint256) {
return _balanceOfByPartition[tokenHolder][partition];
}
/**
* @dev Get partitions index of a tokenholder.
* @param tokenHolder Address for which the partitions index are returned.
* @return Array of partitions index of 'tokenHolder'.
*/
function partitionsOf(address tokenHolder) external override view returns (bytes32[] memory) {
return _partitionsOf[tokenHolder];
}
/************************************************************************************************/
/****************************************** Transfers *******************************************/
/**
* @dev Transfer the amount of tokens from the address 'msg.sender' to the address 'to'.
* @param to Token recipient.
* @param value Number of tokens to transfer.
* @param data Information attached to the transfer, by the token holder.
*/
function transferWithData(address to, uint256 value, bytes calldata data) external override nonReentrant {
_transferByDefaultPartitions(msg.sender, msg.sender, to, value, data);
}
/**
* @dev Transfer the amount of tokens on behalf of the address 'from' to the address 'to'.
* @param from Token holder (or 'address(0)' to set from to 'msg.sender').
* @param to Token recipient.
* @param value Number of tokens to transfer.
* @param data Information attached to the transfer, and intended for the token holder ('from').
*/
function transferFromWithData(address from, address to, uint256 value, bytes calldata data) external override virtual nonReentrant {
require( _isOperator(msg.sender, from)
|| (value <= _allowed[from][msg.sender]), "53"); // 0x53 insufficient allowance
if(_allowed[from][msg.sender] >= value) {
_allowed[from][msg.sender] = _allowed[from][msg.sender] - value;
} else {
_allowed[from][msg.sender] = 0;
}
_transferByDefaultPartitions(msg.sender, from, to, value, data);
}
/************************************************************************************************/
/********************************** Partition Token Transfers ***********************************/
/**
* @dev Transfer tokens from a specific partition.
* @param partition Name of the partition.
* @param to Token recipient.
* @param value Number of tokens to transfer.
* @param data Information attached to the transfer, by the token holder.
* @return Destination partition.
*/
function transferByPartition(
bytes32 partition,
address to,
uint256 value,
bytes calldata data
)
external
override
nonReentrant
returns (bytes32)
{
return _transferByPartition(partition, msg.sender, msg.sender, to, value, data, "");
}
/**
* @dev Transfer tokens from a specific partition through an operator.
* @param partition Name of the partition.
* @param from Token holder.
* @param to Token recipient.
* @param value Number of tokens to transfer.
* @param data Information attached to the transfer. [CAN CONTAIN THE DESTINATION PARTITION]
* @param operatorData Information attached to the transfer, by the operator.
* @return Destination partition.
*/
function operatorTransferByPartition(
bytes32 partition,
address from,
address to,
uint256 value,
bytes calldata data,
bytes calldata operatorData
)
external
override
returns (bytes32)
{
//We want to check if the msg.sender is an authorized operator for `from`
//(msg.sender == from OR msg.sender is authorized by from OR msg.sender is a controller if this token is controlable)
//OR
//We want to check if msg.sender is an `allowed` operator/spender for `from`
require(_isOperatorForPartition(partition, msg.sender, from)
|| (value <= _allowedByPartition[partition][from][msg.sender]), "53"); // 0x53 insufficient allowance
if(_allowedByPartition[partition][from][msg.sender] >= value) {
_allowedByPartition[partition][from][msg.sender] = _allowedByPartition[partition][from][msg.sender] - value;
} else {
_allowedByPartition[partition][from][msg.sender] = 0;
}
return _transferByPartition(partition, msg.sender, from, to, value, data, operatorData);
}
/************************************************************************************************/
/************************************* Controller Operation *************************************/
/**
* @dev Know if the token can be controlled by operators.
* If a token returns 'false' for 'isControllable()'' then it MUST always return 'false' in the future.
* @return bool 'true' if the token can still be controlled by operators, 'false' if it can't anymore.
*/
function isControllable() external override view returns (bool) {
return _isControllable;
}
/************************************************************************************************/
/************************************* Operator Management **************************************/
/**
* @dev Set a third party operator address as an operator of 'msg.sender' to transfer
* and redeem tokens on its behalf.
* @param operator Address to set as an operator for 'msg.sender'.
*/
function authorizeOperator(address operator) external override {
require(operator != msg.sender);
_authorizedOperator[operator][msg.sender] = true;
emit AuthorizedOperator(operator, msg.sender);
}
/**
* @dev Remove the right of the operator address to be an operator for 'msg.sender'
* and to transfer and redeem tokens on its behalf.
* @param operator Address to rescind as an operator for 'msg.sender'.
*/
function revokeOperator(address operator) external override {
require(operator != msg.sender);
_authorizedOperator[operator][msg.sender] = false;
emit RevokedOperator(operator, msg.sender);
}
/**
* @dev Set 'operator' as an operator for 'msg.sender' for a given 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 override {
_authorizedOperatorByPartition[msg.sender][partition][operator] = true;
emit AuthorizedOperatorByPartition(partition, operator, msg.sender);
}
/**
* @dev Remove the right of the operator address to be an operator on a given
* partition for 'msg.sender' and to transfer and redeem tokens on its behalf.
* @param partition Name of the partition.
* @param operator Address to rescind as an operator on given partition for 'msg.sender'.
*/
function revokeOperatorByPartition(bytes32 partition, address operator) external override {
_authorizedOperatorByPartition[msg.sender][partition][operator] = false;
emit RevokedOperatorByPartition(partition, operator, msg.sender);
}
/************************************************************************************************/
/************************************* Operator Information *************************************/
/**
* @dev Indicate whether the operator address is an operator of the tokenHolder address.
* @param operator Address which may be an operator of tokenHolder.
* @param tokenHolder Address of a token holder which may have the operator address as an operator.
* @return 'true' if operator is an operator of 'tokenHolder' and 'false' otherwise.
*/
function isOperator(address operator, address tokenHolder) external override view returns (bool) {
re...
// [truncated — 98152 bytes total]
Read Contract
FOR_SALE_TOKENS 0x4d8fae95 → uint256
ISSUED_TOKENS 0x81552f58 → uint256
NSDQ_DEFAULT_PARTITION 0x22400f4e → bytes32
allowance 0xdd62ed3e → uint256
allowanceByPartition 0x17ec83ca → uint256
balanceOf 0x70a08231 → uint256
balanceOfByPartition 0x30e82803 → uint256
canImplementInterfaceForAddress 0x249cb3fa → bytes32
canOperatorTransferByPartition 0x6c23c7b0 → bytes1, bytes32, bytes32
canTransferByPartition 0x92127126 → bytes1, bytes32, bytes32
controllers 0x7cc0c3a7 → address[]
controllersByPartition 0x861ed3ea → address[]
decimals 0x313ce567 → uint8
domainName 0x895d7386 → string
domainVersion 0x1d43e1c0 → string
generateDomainSeparator 0xa8082cb0 → bytes32
getAllDocuments 0x9fa5f50b → bytes32[]
getDefaultPartitions 0xbcfdc0cf → bytes32[]
getDocument 0xb10d6b41 → string, bytes32, uint256
granularity 0x556f0dc7 → uint256
isControllable 0x4c783bf5 → bool
isIssuable 0x2f1cae85 → bool
isMinter 0xaa271e1a → bool
isOperator 0xb6363cf2 → bool
isOperatorForPartition 0x6d77cad6 → bool
name 0x06fdde03 → string
owner 0x8da5cb5b → address
partitionsOf 0x740ab8f4 → bytes32[]
symbol 0x95d89b41 → string
totalPartitions 0x69598efe → bytes32[]
totalSupply 0x18160ddd → uint256
totalSupplyByPartition 0xa26734dc → uint256
Write Contract 34 functions
These functions modify contract state and require a wallet transaction to execute.
addMinter 0x983b2d56
address account
approve 0x095ea7b3
address spender
uint256 value
returns: bool
approveByPartition 0x14d1e62f
bytes32 partition
address spender
uint256 value
returns: bool
authorizeOperator 0x959b8c3f
address operator
authorizeOperatorByPartition 0x103ef9e1
bytes32 partition
address operator
domainSeparator 0xf698da25
No parameters
returns: bytes32
initExtention 0x8853ce83
address extension
address certificateSigner
uint8 certificateActivated
address[] controllers_
issue 0xbb3acde9
address tokenHolder
uint256 value
bytes data
issueByPartition 0x67c84919
bytes32 partition
address tokenHolder
uint256 value
bytes data
migrate 0x933964c7
address newContractAddress
bool definitive
operatorRedeemByPartition 0x98ddcec7
bytes32 partition
address tokenHolder
uint256 value
bytes operatorData
operatorTransferByPartition 0x8c0dee9c
bytes32 partition
address from
address to
uint256 value
bytes data
bytes operatorData
returns: bytes32
redeem 0xe77c646d
uint256 value
bytes data
redeemByPartition 0x62eb0068
bytes32 partition
uint256 value
bytes data
redeemFrom 0x9675193c
address from
uint256 value
bytes data
removeDocument 0xc3501848
bytes32 shortName
removeMinter 0x3092afd5
address account
renounceControl 0xca281fd9
No parameters
renounceIssuance 0x6c30d170
No parameters
renounceMinter 0x98650275
No parameters
renounceOwnership 0x715018a6
No parameters
revokeOperator 0xfad8b32a
address operator
revokeOperatorByPartition 0x168ecec5
bytes32 partition
address operator
setControllers 0xea74838a
address[] operators
setDefaultPartitions 0xec9a6e87
bytes32[] partitions
setDocument 0x010648ca
bytes32 shortName
string uri
bytes32 documentHash
setPartitionControllers 0x16e1aed4
bytes32 partition
address[] operators
setTokenExtension 0xa6f4f105
address extension
string interfaceLabel
bool removeOldExtensionRoles
bool addMinterRoleForExtension
bool addControllerRoleForExtension
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferByPartition 0xf3d490db
bytes32 partition
address to
uint256 value
bytes data
returns: bytes32
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool
transferFromWithData 0xee532f31
address from
address to
uint256 value
bytes data
transferOwnership 0xf2fde38b
address newOwner
transferWithData 0x2535f762
address to
uint256 value
bytes data
Recent Transactions
No transactions found for this address