Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xa2922d85C8EB4072bEd71d37273E9DA9f4c03314
Balance 0 ETH
Nonce 1
Code Size 9621 bytes
Indexed Transactions Index loading...
External Etherscan · Sourcify

Contract Bytecode

9621 bytes
0x608060405234801561001057600080fd5b5060043610610218576000357c0100000000000000000000000000000000000000000000000000000000900480638140d0dc11610137578063c6786e5a116100ca578063dd62ed3e11610099578063dd62ed3e146106d0578063e46638e6146106fe578063f0eb5e5414610734578063f2fde38b1461075a578063fcf196b41461078057610218565b8063c6786e5a146105f0578063cc872b6614610660578063d4ce14151461067d578063db006a75146106b357610218565b806395d89b411161010657806395d89b411461056a578063a457c2d714610572578063a4a0a3011461059e578063a9059cbb146105c457610218565b80638140d0dc146104a857806382dc1ec4146105185780638456cb591461053e5780638da5cb5b1461054657610218565b806346fbf68e116101af5780636ef8d66d1161017e5780636ef8d66d1461045257806370a082311461045a578063715018a6146104805780637f4ab1dd1461048857610218565b806346fbf68e146103865780635c975abb146103ac5780635fff8cd3146103b4578063630e327d146103e257610218565b8063313ce567116101eb578063313ce5671461032a57806333a8c45a1461034857806339509351146103505780633f4ba83a1461037c57610218565b806306fdde031461021d578063095ea7b31461029a57806318160ddd146102da57806323b872dd146102f4575b600080fd5b610225610788565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561025f578181015183820152602001610247565b50505050905090810190601f16801561028c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102c6600480360360408110156102b057600080fd5b50600160a060020a038135169060200135610816565b604080519115158252519081900360200190f35b6102e2610875565b60408051918252519081900360200190f35b6102c66004803603606081101561030a57600080fd5b50600160a060020a0381358116916020810135909116906040013561087c565b6103326109e7565b6040805160ff9092168252519081900360200190f35b6102256109ec565b6102c66004803603604081101561036657600080fd5b50600160a060020a038135169060200135610a47565b610384610a9d565b005b6102c66004803603602081101561039c57600080fd5b5035600160a060020a0316610b81565b6102c6610b9c565b610384600480360360408110156103ca57600080fd5b50600160a060020a0381358116916020013516610ba5565b610384600480360360208110156103f857600080fd5b81019060208101813564010000000081111561041357600080fd5b82018360208201111561042557600080fd5b8035906020019184600183028401116401000000008311171561044757600080fd5b509092509050610e9e565b610384610ebd565b6102e26004803603602081101561047057600080fd5b5035600160a060020a0316610ec8565b610384610ee3565b6102256004803603602081101561049e57600080fd5b503560ff16610f88565b610384600480360360208110156104be57600080fd5b8101906020810181356401000000008111156104d957600080fd5b8201836020820111156104eb57600080fd5b8035906020019184600183028401116401000000008311171561050d57600080fd5b50909250905061111c565b6103846004803603602081101561052e57600080fd5b5035600160a060020a03166111db565b610384611230565b61054e611304565b60408051600160a060020a039092168252519081900360200190f35b610225611313565b6102c66004803603604081101561058857600080fd5b50600160a060020a03813516906020013561136e565b610384600480360360208110156105b457600080fd5b5035600160a060020a03166113c4565b6102c6600480360360408110156105da57600080fd5b50600160a060020a038135169060200135611469565b6103846004803603602081101561060657600080fd5b81019060208101813564010000000081111561062157600080fd5b82018360208201111561063357600080fd5b8035906020019184602083028401116401000000008311171561065557600080fd5b5090925090506115ce565b6103846004803603602081101561067657600080fd5b5035611821565b6103326004803603606081101561069357600080fd5b50600160a060020a03813581169160208101359091169060400135611935565b610384600480360360208110156106c957600080fd5b5035611a0f565b6102e2600480360360408110156106e657600080fd5b50600160a060020a0381358116916020013516611b21565b6102c66004803603606081101561071457600080fd5b50600160a060020a03813581169160208101359091169060400135611b4c565b6102256004803603602081101561074a57600080fd5b5035600160a060020a0316611bf3565b6103846004803603602081101561077057600080fd5b5035600160a060020a0316611c9e565b61054e611cf5565b6006805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561080e5780601f106107e35761010080835404028352916020019161080e565b820191906000526020600020905b8154815290600101906020018083116107f157829003601f168201915b505050505081565b60055460009060ff1615610862576040805160e560020a62461bcd0281526020600482015260106024820152600080516020612526833981519152604482015290519081900360640190fd5b61086c8383611d04565b90505b92915050565b6002545b90565b60055460009060ff16156108c8576040805160e560020a62461bcd0281526020600482015260106024820152600080516020612526833981519152604482015290519081900360640190fd5b600a54600160a060020a0316156109d257600a54604080517fc6946a12000000000000000000000000000000000000000000000000000000008152600160a060020a0387811660048301528681166024830152604482018690529151919092169163c6946a12916064808301926020929190829003018186803b15801561094e57600080fd5b505afa158015610962573d6000803e3d6000fd5b505050506040513d602081101561097857600080fd5b505115156109d2576040805160e560020a62461bcd028152602060048083019190915260248201527f434d303400000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6109dd848484611d1a565b90505b9392505050565b600081565b6008805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561080e5780601f106107e35761010080835404028352916020019161080e565b60055460009060ff1615610a93576040805160e560020a62461bcd0281526020600482015260106024820152600080516020612526833981519152604482015290519081900360640190fd5b61086c8383611d67565b610aa633610b81565b1515610ae65760405160e560020a62461bcd02815260040180806020018281038252603081526020018061244c6030913960400191505060405180910390fd5b60055460ff161515610b42576040805160e560020a62461bcd02815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b6005805460ff191690556040805133815290517f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa9181900360200190a1565b6000610b9460048363ffffffff611da316565b90505b919050565b60055460ff1690565b600354600160a060020a03163314610bf3576040805160e560020a62461bcd0281526020600480830191909152602482015260e060020a634f57303102604482015290519081900360640190fd5b60055460ff1615610c3c576040805160e560020a62461bcd0281526020600482015260106024820152600080516020612526833981519152604482015290519081900360640190fd5b600160a060020a0382161515610c9e576040805160e560020a62461bcd028152602060048083019190915260248201527f434d303100000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0381161515610d00576040805160e560020a62461bcd028152602060048083019190915260248201527f434d303200000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038281169082161415610d66576040805160e560020a62461bcd028152602060048083019190915260248201527f434d303300000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038216600090815260208190526040902054801515610dd8576040805160e560020a62461bcd028152602060048083019190915260248201527f434d303500000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038216600090815260208190526040902054610e01908263ffffffff611e0f16565b600160a060020a03808416600081815260208181526040808320959095559287168082528482209190915583518581529351919390926000805160206124e183398151915292918290030190a381600160a060020a031683600160a060020a03167f9b50bb42c2f723a111ed2b4a02d7963b78fcef409123755e32db36acf004c721836040518082815260200191505060405180910390a3505050565b336000908152600960205260409020610eb8908383612390565b505050565b610ec633611e6c565b565b600160a060020a031660009081526020819052604090205490565b600354600160a060020a03163314610f31576040805160e560020a62461bcd0281526020600480830191909152602482015260e060020a634f57303102604482015290519081900360640190fd5b600354604051600160a060020a03909116907ff8df31144d9c2f0f6b59d69b8b98abd5459d07f2742c4df920b25aae33c6482090600090a26003805473ffffffffffffffffffffffffffffffffffffffff19169055565b606060ff82161515610fce575060408051808201909152600e81527f4e6f207265737472696374696f6e0000000000000000000000000000000000006020820152610b97565b60ff821660011415611014575060408051808201909152601481527f416c6c207472616e7366657273207061757365640000000000000000000000006020820152610b97565b600a54600160a060020a031615610b9757600a54604080517f7f4ab1dd00000000000000000000000000000000000000000000000000000000815260ff851660048201529051600160a060020a0390921691637f4ab1dd91602480820192600092909190829003018186803b15801561108c57600080fd5b505afa1580156110a0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156110c957600080fd5b8101908080516401000000008111156110e157600080fd5b820160208101848111156110f457600080fd5b815164010000000081118282018710171561110e57600080fd5b50909450610b979350505050565b600354600160a060020a0316331461116a576040805160e560020a62461bcd0281526020600480830191909152602482015260e060020a634f57303102604482015290519081900360640190fd5b61117660088383612390565b507f188bad42ea723dd12513086ade62bd9d922818bd71ec4761f9b66c171c17dd0d828260405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b6111e433610b81565b15156112245760405160e560020a62461bcd02815260040180806020018281038252603081526020018061244c6030913960400191505060405180910390fd5b61122d81611eb4565b50565b61123933610b81565b15156112795760405160e560020a62461bcd02815260040180806020018281038252603081526020018061244c6030913960400191505060405180910390fd5b60055460ff16156112c2576040805160e560020a62461bcd0281526020600482015260106024820152600080516020612526833981519152604482015290519081900360640190fd5b6005805460ff191660011790556040805133815290517f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2589181900360200190a1565b600354600160a060020a031681565b6007805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561080e5780601f106107e35761010080835404028352916020019161080e565b60055460009060ff16156113ba576040805160e560020a62461bcd0281526020600482015260106024820152600080516020612526833981519152604482015290519081900360640190fd5b61086c8383611efc565b600354600160a060020a03163314611412576040805160e560020a62461bcd0281526020600480830191909152602482015260e060020a634f57303102604482015290519081900360640190fd5b600a805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383169081179091556040517fc821fee57f621fad293a6960b94de2653a70bcc62506ea4f85149777b45901fe90600090a250565b60055460009060ff16156114b5576040805160e560020a62461bcd0281526020600482015260106024820152600080516020612526833981519152604482015290519081900360640190fd5b600a54600160a060020a0316156115bd57600a54604080517fc6946a12000000000000000000000000000000000000000000000000000000008152336004820152600160a060020a038681166024830152604482018690529151919092169163c6946a12916064808301926020929190829003018186803b15801561153957600080fd5b505afa15801561154d573d6000803e3d6000fd5b505050506040513d602081101561156357600080fd5b505115156115bd576040805160e560020a62461bcd028152602060048083019190915260248201527f434d303400000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6115c78383611f38565b905061086f565b600354600160a060020a0316331461161c576040805160e560020a62461bcd0281526020600480830191909152602482015260e060020a634f57303102604482015290519081900360640190fd5b60005b818110156117b957600354600160a060020a031683838381811061163f57fe5b90506020020135600160a060020a0316600160a060020a0316141515156116b2576040805160e560020a62461bcd028152602060048083019190915260248201527f434d303600000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600080808585858181106116c257fe5b600160a060020a0360209182029390930135831684528381019490945250604091820160009081205460035490921681529283905291205490915061170d908263ffffffff611e0f16565b600354600160a060020a0316600090815260208190526040812091909155808086868681811061173957fe5b600160a060020a036020918202939093013583168452830193909352604090910160002092909255506003541684848481811061177257fe5b90506020020135600160a060020a0316600160a060020a03166000805160206124e1833981519152836040518082815260200191505060405180910390a35060010161161f565b507fef8a7d1d9ed56b75ba2d074c0443d09a07e60674f3f6d4e992e9bda38efe5880828260405180806020018281038252848482818152602001925060200280828437600083820152604051601f909101601f19169092018290039550909350505050a15050565b600354600160a060020a0316331461186f576040805160e560020a62461bcd0281526020600480830191909152602482015260e060020a634f57303102604482015290519081900360640190fd5b600354600160a060020a031660009081526020819052604090205461189a908263ffffffff611e0f16565b600354600160a060020a03166000908152602081905260409020556002546118c8908263ffffffff611e0f16565b600255600354604080518381529051600160a060020a03909216916000916000805160206124e1833981519152919081900360200190a36040805182815290517f5aa5d4dbb3bdc35fe42446ba12fc59cdd56ee008d5a8159ba5e5fb5834734f629181900360200190a150565b600061193f610b9c565b1561194c575060016109e0565b600a54600160a060020a031615611a0557600a54604080517fd4ce1415000000000000000000000000000000000000000000000000000000008152600160a060020a0387811660048301528681166024830152604482018690529151919092169163d4ce1415916064808301926020929190829003018186803b1580156119d257600080fd5b505afa1580156119e6573d6000803e3d6000fd5b505050506040513d60208110156119fc57600080fd5b505190506109e0565b5060009392505050565b600354600160a060020a03163314611a5d576040805160e560020a62461bcd0281526020600480830191909152602482015260e060020a634f57303102604482015290519081900360640190fd5b600354600160a060020a0316600090815260208190526040902054611a88908263ffffffff611f4516565b600354600160a060020a0316600090815260208190526040902055600254611ab6908263ffffffff611f4516565b600255600354604080518381529051600092600160a060020a0316916000805160206124e1833981519152919081900360200190a36040805182815290517fe3dd692f7e5c129a26d85142bf6118f2ecf7722a79a4507ac05ad7bb7aaab1529181900360200190a150565b600160a060020a03918216600090815260016020908152604080832093909416825291909152205490565b6000611b56610b9c565b15611b63575060006109e0565b600a54600160a060020a031615611be957600a54604080517fc6946a12000000000000000000000000000000000000000000000000000000008152600160a060020a0387811660048301528681166024830152604482018690529151919092169163c6946a12916064808301926020929190829003018186803b1580156119d257600080fd5b5060019392505050565b600160a060020a03811660009081526009602090815260409182902080548351601f6002600019610100600186161502019093169290920491820184900484028101840190945280845260609392830182828015611c925780601f10611c6757610100808354040283529160200191611c92565b820191906000526020600020905b815481529060010190602001808311611c7557829003601f168201915b50505050509050919050565b600354600160a060020a03163314611cec576040805160e560020a62461bcd0281526020600480830191909152602482015260e060020a634f57303102604482015290519081900360640190fd5b61122d81611fa5565b600a54600160a060020a031681565b6000611d11338484612070565b50600192915050565b6000611d27848484612166565b600160a060020a038416600090815260016020908152604080832033808552925290912054611be9918691611d62908663ffffffff611f4516565b612070565b336000818152600160209081526040808320600160a060020a03871684529091528120549091611d11918590611d62908663ffffffff611e0f16565b6000600160a060020a0382161515611def5760405160e560020a62461bcd0281526004018080602001828103825260228152602001806124bf6022913960400191505060405180910390fd5b50600160a060020a03166000908152602091909152604090205460ff1690565b60008282018381101561086c576040805160e560020a62461bcd02815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b611e7d60048263ffffffff6122a016565b604051600160a060020a038216907fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e90600090a250565b611ec560048263ffffffff61230c16565b604051600160a060020a038216907f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f890600090a250565b336000818152600160209081526040808320600160a060020a03871684529091528120549091611d11918590611d62908663ffffffff611f4516565b6000611d11338484612166565b600082821115611f9f576040805160e560020a62461bcd02815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600160a060020a0381161515612007576040805160e560020a62461bcd028152602060048083019190915260248201527f4f57303200000000000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b600354604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36003805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600160a060020a03831615156120ba5760405160e560020a62461bcd0281526004018080602001828103825260248152602001806125466024913960400191505060405180910390fd5b600160a060020a03821615156121045760405160e560020a62461bcd02815260040180806020018281038252602281526020018061247c6022913960400191505060405180910390fd5b600160a060020a03808416600081815260016020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b600160a060020a03831615156121b05760405160e560020a62461bcd0281526004018080602001828103825260258152602001806125016025913960400191505060405180910390fd5b600160a060020a03821615156121fa5760405160e560020a62461bcd0281526004018080602001828103825260238152602001806124296023913960400191505060405180910390fd5b600160a060020a038316600090815260208190526040902054612223908263ffffffff611f4516565b600160a060020a038085166000908152602081905260408082209390935590841681522054612258908263ffffffff611e0f16565b600160a060020a038084166000818152602081815260409182902094909455805185815290519193928716926000805160206124e183398151915292918290030190a3505050565b6122aa8282611da3565b15156122ea5760405160e560020a62461bcd02815260040180806020018281038252602181526020018061249e6021913960400191505060405180910390fd5b600160a060020a0316600090815260209190915260409020805460ff19169055565b6123168282611da3565b1561236b576040805160e560020a62461bcd02815260206004820152601f60248201527f526f6c65733a206163636f756e7420616c72656164792068617320726f6c6500604482015290519081900360640190fd5b600160a060020a0316600090815260209190915260409020805460ff19166001179055565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106123d15782800160ff198235161785556123fe565b828001600101855582156123fe579182015b828111156123fe5782358255916020019190600101906123e3565b5061240a92915061240e565b5090565b61087991905b8082111561240a576000815560010161241456fe45524332303a207472616e7366657220746f20746865207a65726f2061646472657373506175736572526f6c653a2063616c6c657220646f6573206e6f742068617665207468652050617573657220726f6c6545524332303a20617070726f766520746f20746865207a65726f2061646472657373526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c65526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef45524332303a207472616e736665722066726f6d20746865207a65726f20616464726573735061757361626c653a207061757365640000000000000000000000000000000045524332303a20617070726f76652066726f6d20746865207a65726f2061646472657373a165627a7a723058205da046d6c5d400046c4c6a148752477ac4c8b6a46b406ce29cb70f48b4663b0f0029

Verified Source Code Partial Match

Compiler: v0.5.3+commit.10d17f24 EVM: byzantium Optimization: Yes (200 runs)
ERC20.sol 228 lines
pragma solidity ^0.5.0;

import "./IERC20.sol";
import "./SafeMath.sol";

/**
 * @dev Implementation of the `IERC20` interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using `_mint`.
 * For a generic mechanism see `ERC20Mintable`.
 *
 * *For a detailed writeup see our guide [How to implement supply
 * mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).*
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an `Approval` event is emitted on calls to `transferFrom`.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard `decreaseAllowance` and `increaseAllowance`
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See `IERC20.approve`.
 */
contract ERC20 is IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) internal _balances;

    mapping (address => mapping (address => uint256)) internal _allowances;

    uint256 internal _totalSupply;

    /**
     * @dev See `IERC20.totalSupply`.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See `IERC20.balanceOf`.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See `IERC20.transfer`.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    /**
     * @dev See `IERC20.allowance`.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See `IERC20.approve`.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev See `IERC20.transferFrom`.
     *
     * Emits an `Approval` event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of `ERC20`;
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `value`.
     * - the caller must have allowance for `sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to `approve` that can be used as a mitigation for
     * problems described in `IERC20.approve`.
     *
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to `approve` that can be used as a mitigation for
     * problems described in `IERC20.approve`.
     *
     * 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`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to `transfer`, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a `Transfer` event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a `Transfer` event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

     /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a `Transfer` event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 value) internal {
        require(account != address(0), "ERC20: burn from the zero address");

        _totalSupply = _totalSupply.sub(value);
        _balances[account] = _balances[account].sub(value);
        emit Transfer(account, address(0), value);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an `Approval` event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * @dev Destoys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See `_burn` and `_approve`.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
    }
}
IRule.sol 27 lines
/* 
 * Copyright (c) Capital Market and Technology Association, 2018-2019
 * https://cmta.ch
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. 
 */

pragma solidity ^0.5.3;

/**
 * @title IRule
 * @dev IRule interface.
 **/
interface IRule {
  function isTransferValid(
    address _from, address _to, uint256 _amount)
  external view returns (bool isValid);

  function detectTransferRestriction(
    address _from, address _to, uint256 _amount)
  external view returns (uint8);

  function canReturnTransferRestrictionCode(uint8 _restrictionCode) external view returns (bool);
  function messageForTransferRestriction(uint8 _restrictionCode) external view returns (string memory);
}
Roles.sol 36 lines
pragma solidity ^0.5.0;

/**
 * @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];
    }
}
CMTA20.sol 287 lines
/*
 * Copyright (c) Capital Market and Technology Association, 2018-2019
 * https://cmta.ch
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

pragma solidity ^0.5.3;

import "./SafeMath.sol";
import "./ERC20.sol";
import "./Pausable.sol";
import "./Ownable.sol";
import "./IIssuable.sol";
import "./IDestroyable.sol";
import "./IReassignable.sol";
import "./IIdentifiable.sol";
import "./IContactable.sol";
import "./IRuleEngine.sol";

/**
 * @title CMTA20
 * @dev CMTA20 contract
 *
 * @author Sébastien Krafft - <[email protected]>
 *
 * errors:
 * CM01: Attempt to reassign from an original address which is 0x0
 * CM02: Attempt to reassign to a replacement address is 0x0
 * CM03: Attempt to reassign to replacement address which is the same as the original address
 * CM04: Transfer rejected by Rule Engine
 * CM05: Attempt to reassign from an original address which does not have any tokens
 * CM06: Cannot call destroy with owner address contained in parameter
 */


contract CMTA20 is ERC20, Ownable, Pausable, IContactable, IIdentifiable, IIssuable, IDestroyable, IReassignable {
  using SafeMath for uint256;

  /* Constants */
  uint8 constant TRANSFER_OK = 0;
  uint8 constant TRANSFER_REJECTED_PAUSED = 1;

  string constant TEXT_TRANSFER_OK = "No restriction";
  string constant TEXT_TRANSFER_REJECTED_PAUSED = "All transfers paused";

  string public name;
  string public symbol;
  string public contact;
  mapping (address => bytes) internal identities;
  IRuleEngine public ruleEngine;

  // solium-disable-next-line uppercase
  uint8 constant public decimals = 0;

  constructor(string memory _name, string memory _symbol, string memory _contact) public {
    name = _name;
    symbol = _symbol;
    contact = _contact;
  }

  event LogRuleEngineSet(address indexed newRuleEngine);

  /**
  * Purpose
  * Set optional rule engine by owner
  *
  * @param _ruleEngine - the rule engine that will approve/reject transfers
  */
  function setRuleEngine(IRuleEngine _ruleEngine) external onlyOwner {
    ruleEngine = _ruleEngine;
    emit LogRuleEngineSet(address(_ruleEngine));
  }

  /**
  * Purpose
  * Set contact point for shareholders
  *
  * @param _contact - the contact information for the shareholders
  */
  function setContact(string calldata _contact) external onlyOwner {
    contact = _contact;
    emit LogContactSet(_contact);
  }

  /**
  * Purpose
  * Retrieve identity of a potential/actual shareholder
  */
  function identity(address shareholder) external view returns (bytes memory) {
    return identities[shareholder];
  }

  /**
  * Purpose
  * Set identity of a potential/actual shareholder. Can only be called by the potential/actual shareholder himself. Has to be encrypted data.
  *
  * @param _identity - the potential/actual shareholder identity
  */
  function setMyIdentity(bytes calldata _identity) external {
    identities[msg.sender] = _identity;
  }

  /**
  * Purpose:
  * Issue tokens on the owner address
  *
  * @param _value - amount of newly issued tokens
  */
  function issue(uint256 _value) public onlyOwner {
    _balances[owner] = _balances[owner].add(_value);
    _totalSupply = _totalSupply.add(_value);

    emit Transfer(address(0), owner, _value);
    emit LogIssued(_value);
  }

  /**
  * Purpose:
  * Redeem tokens on the owner address
  *
  * @param _value - amount of redeemed tokens
  */
  function redeem(uint256 _value) public onlyOwner {
    _balances[owner] = _balances[owner].sub(_value);
    _totalSupply = _totalSupply.sub(_value);

    emit Transfer(owner, address(0), _value);
    emit LogRedeemed(_value);
  }

  /**
  * @dev check if _value token can be transferred from _from to _to
  * @param _from address The address which you want to send tokens from
  * @param _to address The address which you want to transfer to
  * @param _value uint256 the amount of tokens to be transferred
  */
  function canTransfer(address _from, address _to, uint256 _value) public view returns (bool) {
    if (paused()) {
      return false;
    }
    if (address(ruleEngine) != address(0)) {
      return ruleEngine.validateTransfer(_from, _to, _value);
    }
    return true;
  }

  /**
  * @dev check if _value token can be transferred from _from to _to
  * @param _from address The address which you want to send tokens from
  * @param _to address The address which you want to transfer to
  * @param _value uint256 the amount of tokens to be transferred
  * @return code of the rejection reason
  */
  function detectTransferRestriction (address _from, address _to, uint256 _value) public view returns (uint8) {
    if (paused()) {
      return TRANSFER_REJECTED_PAUSED;
    }
    if (address(ruleEngine) != address(0)) {
      return ruleEngine.detectTransferRestriction(_from, _to, _value);
    }
    return TRANSFER_OK;
  }

  /**
  * @dev returns the human readable explaination corresponding to the error code returned by detectTransferRestriction
  * @param _restrictionCode The error code returned by detectTransferRestriction
  * @return The human readable explaination corresponding to the error code returned by detectTransferRestriction
  */
  function messageForTransferRestriction (uint8 _restrictionCode) external view returns (string memory) {
    if (_restrictionCode == TRANSFER_OK) {
      return TEXT_TRANSFER_OK;
    } else if (_restrictionCode == TRANSFER_REJECTED_PAUSED) {
      return TEXT_TRANSFER_REJECTED_PAUSED;
    } else if (address(ruleEngine) != address(0)) {
      return ruleEngine.messageForTransferRestriction(_restrictionCode);
    }
  }

  /**
  * @dev transfer token for a specified address
  * @param _to The address to transfer to.
  * @param _value The amount to be transferred.
  */
  function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) {
    if (address(ruleEngine) != address(0)) {
      require(ruleEngine.validateTransfer(msg.sender, _to, _value), "CM04");
      return super.transfer(_to, _value);
    } else {
      return super.transfer(_to, _value);
    }
  }

  /**
   * @dev Transfer tokens from one address to another
   * @param _from address The address which you want to send tokens from
   * @param _to address The address which you want to transfer to
   * @param _value uint256 the amount of tokens to be transferred
   */
  function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) {
    if (address(ruleEngine) != address(0)) {
      require(ruleEngine.validateTransfer(_from, _to, _value), "CM04");
      return super.transferFrom(_from, _to, _value);
    } else {
      return super.transferFrom(_from, _to, _value);
    }
  }

  /**
   * @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.
   */
  function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) {
    return super.approve(_spender, _value);
  }

  /**
   * @dev Increase the amount of tokens that an owner allowed to a spender.
   *
   * @param _spender The address which will spend the funds.
   * @param _addedValue The amount of tokens to increase the allowance by.
   */
  function increaseAllowance(address _spender, uint256 _addedValue) public whenNotPaused returns (bool)
  {
    return super.increaseAllowance(_spender, _addedValue);
  }

  /**
   * @dev Decrease the amount of tokens that an owner allowed to a spender.
   *
   * @param _spender The address which will spend the funds.
   * @param _subtractedValue The amount of tokens to decrease the allowance by.
   */
  function decreaseAllowance(address _spender, uint256 _subtractedValue) public whenNotPaused returns (bool)
  {
    return super.decreaseAllowance(_spender, _subtractedValue);
  }

  /**
  * Purpose:
  * To withdraw tokens from the original address and
  * transfer those tokens to the replacement address.
  * Use in cases when e.g. investor loses access to his account.
  *
  * Conditions:
  * Throw error if the `original` address supplied is not a shareholder.
  * Only issuer can execute this function.
  *
  * @param original - original address
  * @param replacement - replacement address
    */
  function reassign(address original, address replacement) external onlyOwner whenNotPaused {
    require(original != address(0), "CM01");
    require(replacement != address(0), "CM02");
    require(original != replacement, "CM03");
    uint256 originalBalance = _balances[original];
    require(originalBalance != 0, "CM05");
    _balances[replacement] = _balances[replacement].add(originalBalance);
    _balances[original] = 0;
    emit Transfer(original, replacement, originalBalance);
    emit LogReassigned(original, replacement, originalBalance);
  }

  /**
  * Purpose;
  * To destroy issued tokens.
  *
  * Conditions:
  * Only issuer can execute this function.
  *
  * @param shareholders - list of shareholders
  */
  function destroy(address[] calldata shareholders) external onlyOwner {
    for (uint256 i = 0; i<shareholders.length; i++) {
      require(shareholders[i] != owner, "CM06");
      uint256 shareholderBalance = _balances[shareholders[i]];
      _balances[owner] = _balances[owner].add(shareholderBalance);
      _balances[shareholders[i]] = 0;
      emit Transfer(shareholders[i], owner, shareholderBalance);
    }
    emit LogDestroyed(shareholders);
  }
}
IERC20.sol 76 lines
pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see `ERC20Detailed`.
 */
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.
     *
     * > 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);
}
Ownable.sol 64 lines
pragma solidity ^0.5.0;


/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 * errors
 * OW01: Sender is not owner
 * OW02: Trying to set owner to 0x0
 */
contract Ownable {
  address public owner;


  event OwnershipRenounced(address indexed previousOwner);
  event OwnershipTransferred(
    address indexed previousOwner,
    address indexed newOwner
  );


  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  constructor() public {
    owner = msg.sender;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner, "OW01");
    _;
  }

  /**
   * @dev Allows the current owner to relinquish control of the contract.
   */
  function renounceOwnership() public onlyOwner {
    emit OwnershipRenounced(owner);
    owner = address(0);
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function transferOwnership(address _newOwner) public onlyOwner {
    _transferOwnership(_newOwner);
  }

  /**
   * @dev Transfers control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function _transferOwnership(address _newOwner) internal {
    require(_newOwner != address(0), "OW02");
    emit OwnershipTransferred(owner, _newOwner);
    owner = _newOwner;
  }
}
Pausable.sol 73 lines
pragma solidity ^0.5.0;

import "./PauserRole.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
contract Pausable is PauserRole {
    /**
     * @dev Emitted when the pause is triggered by a pauser (`account`).
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by a pauser (`account`).
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state. Assigns the Pauser role
     * to the deployer.
     */
    constructor () internal {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     */
    modifier whenNotPaused() {
        require(!_paused, "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     */
    modifier whenPaused() {
        require(_paused, "Pausable: not paused");
        _;
    }

    /**
     * @dev Called by a pauser to pause, triggers stopped state.
     */
    function pause() public onlyPauser whenNotPaused {
        _paused = true;
        emit Paused(msg.sender);
    }

    /**
     * @dev Called by a pauser to unpause, returns to normal state.
     */
    function unpause() public onlyPauser whenPaused {
        _paused = false;
        emit Unpaused(msg.sender);
    }
}
SafeMath.sol 107 lines
pragma solidity ^0.5.0;

/**
 * @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) {
        require(b <= a, "SafeMath: subtraction overflow");
        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-solidity/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) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        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) {
        require(b != 0, "SafeMath: modulo by zero");
        return a % b;
    }
}
IIssuable.sol 39 lines
/* 
 * Copyright (c) Capital Market and Technology Association, 2018-2019
 * https://cmta.ch
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. 
 */
 
pragma solidity ^0.5.3;

/**
 * @title IIssuable
 * @dev IIssuable interface
 *
 * @author Sébastien Krafft - <[email protected]>
 *
 **/


interface IIssuable {
  function issue(uint256 value) external;
  function redeem(uint256 value) external;
  /**
  * Purpose:
  * This event is emitted when new tokens are issued.
  *
  * @param value - amount of newly issued tokens
  */
  event LogIssued(uint256 value);

  /**
  * Purpose:
  * This event is emitted when tokens are redeemed.
  *
  * @param value - amount of redeemed tokens
  */
  event LogRedeemed(uint256 value);
}
PauserRole.sol 43 lines
pragma solidity ^0.5.0;

import "./Roles.sol";

contract PauserRole {
    using Roles for Roles.Role;

    event PauserAdded(address indexed account);
    event PauserRemoved(address indexed account);

    Roles.Role private _pausers;

    constructor () internal {
        _addPauser(msg.sender);
    }

    modifier onlyPauser() {
        require(isPauser(msg.sender), "PauserRole: caller does not have the Pauser role");
        _;
    }

    function isPauser(address account) public view returns (bool) {
        return _pausers.has(account);
    }

    function addPauser(address account) public onlyPauser {
        _addPauser(account);
    }

    function renouncePauser() public {
        _removePauser(msg.sender);
    }

    function _addPauser(address account) internal {
        _pausers.add(account);
        emit PauserAdded(account);
    }

    function _removePauser(address account) internal {
        _pausers.remove(account);
        emit PauserRemoved(account);
    }
}
IRuleEngine.sol 41 lines
/* 
 * Copyright (c) Capital Market and Technology Association, 2018-2019
 * https://cmta.ch
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. 
 */
 
pragma solidity ^0.5.3;


import "./IRule.sol";

/**
 * @title IRuleEngine
 * @dev IRuleEngine 
 **/


interface IRuleEngine {

  function setRules(IRule[] calldata rules) external;
  function ruleLength() external view returns (uint256);
  function rule(uint256 ruleId) external view returns (IRule);
  function rules() external view returns(IRule[] memory);

  function validateTransfer(
    address _from,
    address _to,
    uint256 _amount)
  external view returns (bool);

  function detectTransferRestriction (
    address _from,
    address _to,
    uint256 _value)
  external view returns (uint8);

  function messageForTransferRestriction (uint8 _restrictionCode) external view returns (string memory);
}
IContactable.sol 32 lines
/* 
 * Copyright (c) Capital Market and Technology Association, 2018-2019
 * https://cmta.ch
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. 
 */

pragma solidity ^0.5.3;

/**
 * @title IContactable
 * @dev IContactable interface
 *
 * @author Sébastien Krafft - <[email protected]>
 *
 **/


interface IContactable {
  function contact() external view returns (string memory);
  function setContact(string calldata _contact) external;

  /**
  * Purpose:
  * This event is emitted when the contact information is changed
  *
  * @param contact - new contact information
  */
  event LogContactSet(string contact);
}
IDestroyable.sol 40 lines
/* 
 * Copyright (c) Capital Market and Technology Association, 2018-2019
 * https://cmta.ch
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. 
 */

pragma solidity ^0.5.3;

/**
 * @title IDestroyable
 * @dev IDestroyable interface
 *
 * @author Sébastien Krafft - <[email protected]>
 *
 **/
 

interface IDestroyable {
  /**
  * Purpose;
  * To destroy issued tokens.
  *
  * Conditions:
  * Only issuer can execute this function.
  *
  * @param shareholders - list of shareholders
  */
  function destroy(address[] calldata shareholders) external;

  /**
  * Purpose:
  * This event is emitted when issued tokens are destroyed.
  *
  * @param shareholders - list of shareholders of destroyed tokens
  */
  event LogDestroyed(address[] shareholders);
}
IIdentifiable.sol 24 lines
/* 
 * Copyright (c) Capital Market and Technology Association, 2018-2019
 * https://cmta.ch
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. 
 */
 
pragma solidity ^0.5.3;

/**
 * @title IIdentifiable
 * @dev IIdentifiable interface
 *
 * @author Sébastien Krafft - <[email protected]>
 *
 **/


interface IIdentifiable {
  function identity(address shareholder) external view returns (bytes memory);
  function setMyIdentity(bytes calldata _identity) external;
}
IReassignable.sol 57 lines
/* 
 * Copyright (c) Capital Market and Technology Association, 2018-2019
 * https://cmta.ch
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. 
 */
 
pragma solidity ^0.5.3;

/**
 * @title IReassignable
 * @dev IReassignable interface
 *
 * @author Sébastien Krafft - <[email protected]>
 *
 **/
 

interface IReassignable {
  /**
  * Purpose:
  * To withdraw tokens from the original address and
  * transfer those tokens to the replacement address.
  * Use in cases when e.g. investor loses access to his account.
  *
  * Conditions:
  * Throw error if the `original` address supplied is not a shareholder.
  * Throw error if the 'replacement' address already holds tokens.
  * Original address MUST NOT be reused again.
  * Only issuer can execute this function.
  *
  * @param original - original address
  * @param replacement - replacement address
    */
  function reassign(
    address original,
    address replacement
  ) 
    external;

  /**
  * Purpose:
  * This event is emitted when tokens are withdrawn from one address
  * and issued to a new one.
  *
  * @param original - original address
  * @param replacement - replacement address
  * @param value - amount transfered from original to replacement
  */
  event LogReassigned(
    address indexed original,
    address indexed replacement,
    uint256 value
  );
}

Read Contract

allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
canTransfer 0xe46638e6 → bool
contact 0x33a8c45a → string
decimals 0x313ce567 → uint8
detectTransferRestriction 0xd4ce1415 → uint8
identity 0xf0eb5e54 → bytes
isPauser 0x46fbf68e → bool
messageForTransferRestriction 0x7f4ab1dd → string
name 0x06fdde03 → string
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
ruleEngine 0xfcf196b4 → address
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256

Write Contract 18 functions

These functions modify contract state and require a wallet transaction to execute.

addPauser 0x82dc1ec4
address account
approve 0x095ea7b3
address _spender
uint256 _value
returns: bool
decreaseAllowance 0xa457c2d7
address _spender
uint256 _subtractedValue
returns: bool
destroy 0xc6786e5a
address[] shareholders
increaseAllowance 0x39509351
address _spender
uint256 _addedValue
returns: bool
issue 0xcc872b66
uint256 _value
pause 0x8456cb59
No parameters
reassign 0x5fff8cd3
address original
address replacement
redeem 0xdb006a75
uint256 _value
renounceOwnership 0x715018a6
No parameters
renouncePauser 0x6ef8d66d
No parameters
setContact 0x8140d0dc
string _contact
setMyIdentity 0x630e327d
bytes _identity
setRuleEngine 0xa4a0a301
address _ruleEngine
transfer 0xa9059cbb
address _to
uint256 _value
returns: bool
transferFrom 0x23b872dd
address _from
address _to
uint256 _value
returns: bool
transferOwnership 0xf2fde38b
address _newOwner
unpause 0x3f4ba83a
No parameters

Recent Transactions

Transaction index is loading. Only unfinalized transactions are shown while the index starts up.