├── src └── starkware │ └── isd │ ├── solidity │ ├── IActive.sol │ ├── StarkNetToken.sol │ ├── StakingContractStub.sol │ ├── CommonConstants.sol │ ├── TimeLockedTokens.sol │ ├── GlobalUnlock.sol │ ├── LockedTokenCommon.sol │ ├── DelegationSupport.sol │ └── LockedTokenGrant.sol │ ├── third_party │ └── open_zeppelin │ │ ├── token │ │ └── ERC20 │ │ │ ├── extensions │ │ │ ├── IERC20Metadata.sol │ │ │ ├── draft-IERC20Permit.sol │ │ │ ├── draft-ERC20Permit.sol │ │ │ └── ERC20Votes.sol │ │ │ ├── IERC20.sol │ │ │ └── ERC20.sol │ │ ├── utils │ │ ├── Context.sol │ │ ├── introspection │ │ │ ├── IERC165.sol │ │ │ └── ERC165.sol │ │ ├── Counters.sol │ │ ├── Strings.sol │ │ ├── cryptography │ │ │ ├── draft-EIP712.sol │ │ │ └── ECDSA.sol │ │ ├── Address.sol │ │ └── math │ │ │ ├── Math.sol │ │ │ └── SafeCast.sol │ │ ├── governance │ │ └── utils │ │ │ └── IVotes.sol │ │ └── access │ │ ├── IAccessControl.sol │ │ └── AccessControl.sol │ └── CMakeLists.txt └── README.md /src/starkware/isd/solidity/IActive.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0. 2 | pragma solidity ^0.8.16; 3 | 4 | /* 5 | Interface with a function that indicates whether the contract is active. 6 | */ 7 | interface IActive { 8 | /* 9 | Returns true if active. 10 | */ 11 | function isActive() external view returns (bool); 12 | } 13 | -------------------------------------------------------------------------------- /src/starkware/isd/solidity/StarkNetToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0. 2 | pragma solidity ^0.8.16; 3 | 4 | import "starkware/isd/third_party/open_zeppelin/access/AccessControl.sol"; 5 | import "starkware/isd/third_party/open_zeppelin/token/ERC20/extensions/ERC20Votes.sol"; 6 | 7 | string constant NAME = "StarkNet Token"; 8 | string constant SYMBOL = "STRK"; 9 | 10 | contract StarkNetToken is ERC20Votes, AccessControl { 11 | bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); 12 | 13 | constructor() ERC20Permit(NAME) ERC20(NAME, SYMBOL) { 14 | _grantRole(DEFAULT_ADMIN_ROLE, _msgSender()); 15 | } 16 | 17 | function mint(address account, uint256 amount) external onlyRole(MINTER_ROLE) returns (bool) { 18 | _mint(account, amount); 19 | return true; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/token/ERC20/extensions/IERC20Metadata.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "../IERC20.sol"; 7 | 8 | /** 9 | * @dev Interface for the optional metadata functions from the ERC20 standard. 10 | * 11 | * _Available since v4.1._ 12 | */ 13 | interface IERC20Metadata is IERC20 { 14 | /** 15 | * @dev Returns the name of the token. 16 | */ 17 | function name() external view returns (string memory); 18 | 19 | /** 20 | * @dev Returns the symbol of the token. 21 | */ 22 | function symbol() external view returns (string memory); 23 | 24 | /** 25 | * @dev Returns the decimals places of the token. 26 | */ 27 | function decimals() external view returns (uint8); 28 | } 29 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/utils/Context.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev Provides information about the current execution context, including the 8 | * sender of the transaction and its data. While these are generally available 9 | * via msg.sender and msg.data, they should not be accessed in such a direct 10 | * manner, since when dealing with meta-transactions the account sending and 11 | * paying for execution may not be the actual sender (as far as an application 12 | * is concerned). 13 | * 14 | * This contract is only required for intermediate, library-like contracts. 15 | */ 16 | abstract contract Context { 17 | function _msgSender() internal view virtual returns (address) { 18 | return msg.sender; 19 | } 20 | 21 | function _msgData() internal view virtual returns (bytes calldata) { 22 | return msg.data; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/starkware/isd/solidity/StakingContractStub.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0. 2 | pragma solidity ^0.8.16; 3 | 4 | import "starkware/isd/solidity/IActive.sol"; 5 | 6 | /* 7 | This contract is a place holder of no functionality, 8 | that is expected to be placed behind a proxy. 9 | It's intentionally of no functionallity, and blocked from receiving funds. 10 | */ 11 | contract StakingContractStub is IActive { 12 | /* 13 | Returns false to the isActive query, 14 | so that callers would know not to interact with it. 15 | */ 16 | function isActive() external pure override returns (bool) { 17 | return false; 18 | } 19 | 20 | /* 21 | The isFrozen() is required by our Proxy implementation. 22 | */ 23 | function isFrozen() external pure returns (bool) { 24 | return false; 25 | } 26 | 27 | /* 28 | The initialize() is required when placed behind a Proxy. 29 | */ 30 | function initialize(bytes calldata data) external {} 31 | } 32 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/utils/introspection/IERC165.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev Interface of the ERC165 standard, as defined in the 8 | * https://eips.ethereum.org/EIPS/eip-165[EIP]. 9 | * 10 | * Implementers can declare support of contract interfaces, which can then be 11 | * queried by others ({ERC165Checker}). 12 | * 13 | * For an implementation, see {ERC165}. 14 | */ 15 | interface IERC165 { 16 | /** 17 | * @dev Returns true if this contract implements the interface defined by 18 | * `interfaceId`. See the corresponding 19 | * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] 20 | * to learn more about how these ids are created. 21 | * 22 | * This function call must use less than 30 000 gas. 23 | */ 24 | function supportsInterface(bytes4 interfaceId) external view returns (bool); 25 | } 26 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/utils/introspection/ERC165.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "./IERC165.sol"; 7 | 8 | /** 9 | * @dev Implementation of the {IERC165} interface. 10 | * 11 | * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check 12 | * for the additional interface id that will be supported. For example: 13 | * 14 | * ```solidity 15 | * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 16 | * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); 17 | * } 18 | * ``` 19 | * 20 | * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. 21 | */ 22 | abstract contract ERC165 is IERC165 { 23 | /** 24 | * @dev See {IERC165-supportsInterface}. 25 | */ 26 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 27 | return interfaceId == type(IERC165).interfaceId; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/utils/Counters.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @title Counters 8 | * @author Matt Condon (@shrugs) 9 | * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number 10 | * of elements in a mapping, issuing ERC721 ids, or counting request ids. 11 | * 12 | * Include with `using Counters for Counters.Counter;` 13 | */ 14 | library Counters { 15 | struct Counter { 16 | // This variable should never be directly accessed by users of the library: interactions must be restricted to 17 | // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add 18 | // this feature: see https://github.com/ethereum/solidity/issues/4637 19 | uint256 _value; // default: 0 20 | } 21 | 22 | function current(Counter storage counter) internal view returns (uint256) { 23 | return counter._value; 24 | } 25 | 26 | function increment(Counter storage counter) internal { 27 | unchecked { 28 | counter._value += 1; 29 | } 30 | } 31 | 32 | function decrement(Counter storage counter) internal { 33 | uint256 value = counter._value; 34 | require(value > 0, "Counter: decrement overflow"); 35 | unchecked { 36 | counter._value = value - 1; 37 | } 38 | } 39 | 40 | function reset(Counter storage counter) internal { 41 | counter._value = 0; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/starkware/isd/solidity/CommonConstants.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0. 2 | pragma solidity ^0.8.16; 3 | 4 | // The locked tokens from the grant are released gradually over 4 years. 5 | uint256 constant GRANT_LOCKUP_PERIOD = 1461 days; // 4 years. 6 | uint256 constant DEFAULT_DURATION_GLOBAL_TIMELOCK = 365 days; // 1 years. 7 | uint256 constant MAX_DURATION_GLOBAL_TIMELOCK = 731 days; // 2 years. 8 | uint256 constant MIN_UNLOCK_DELAY = 7 days; // 1 week. 9 | bytes32 constant LOCKED_GRANT_ADMIN_ROLE = keccak256("LOCKED_GRANT_ADMIN_ROLE"); 10 | bytes32 constant GLOBAL_TIMELOCK_ADMIN_ROLE = keccak256("GLOBAL_TIMELOCK_ADMIN_ROLE"); 11 | 12 | // This hash value is used as an ID for `DelegateRegistry` 13 | // If the recipient delegates this ID to an agent address, 14 | // that agent can trigger token release. 15 | bytes32 constant LOCKED_TOKEN_RELEASE_AGENT = keccak256("STARKNET_LOCKED_TOKEN_RELEASE_AGENT"); 16 | 17 | // This hash value is used as an ID for `DelegateRegistry` 18 | // If the recipient delegates this ID to an agent address, 19 | // that agent can submit delegation related transactions. 20 | bytes32 constant LOCKED_TOKEN_DELEGATION_AGENT = keccak256( 21 | "STARKNET_LOCKED_TOKEN_DELEGATION_AGENT" 22 | ); 23 | 24 | // The start time of a LockedGrant (T), at the time of granting (t) must be in the time window 25 | // (t - LOCKED_GRANT_MAX_START_PAST_OFFSET, t + LOCKED_GRANT_MAX_START_FUTURE_OFFSET) 26 | // i.e. t - LOCKED_GRANT_MAX_START_PAST_OFFSET < T < t + LOCKED_GRANT_MAX_START_FUTURE_OFFSET. 27 | uint256 constant LOCKED_GRANT_MAX_START_PAST_OFFSET = 182 days; // 6 months. 28 | uint256 constant LOCKED_GRANT_MAX_START_FUTURE_OFFSET = 31 days; // 1 month. 29 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/governance/utils/IVotes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol) 3 | pragma solidity ^0.8.0; 4 | 5 | /** 6 | * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts. 7 | * 8 | * _Available since v4.5._ 9 | */ 10 | interface IVotes { 11 | /** 12 | * @dev Emitted when an account changes their delegate. 13 | */ 14 | event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); 15 | 16 | /** 17 | * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes. 18 | */ 19 | event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance); 20 | 21 | /** 22 | * @dev Returns the current amount of votes that `account` has. 23 | */ 24 | function getVotes(address account) external view returns (uint256); 25 | 26 | /** 27 | * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`). 28 | */ 29 | function getPastVotes(address account, uint256 blockNumber) external view returns (uint256); 30 | 31 | /** 32 | * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`). 33 | * 34 | * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes. 35 | * Votes that have not been delegated are still part of total supply, even though they would not participate in a 36 | * vote. 37 | */ 38 | function getPastTotalSupply(uint256 blockNumber) external view returns (uint256); 39 | 40 | /** 41 | * @dev Returns the delegate that `account` has chosen. 42 | */ 43 | function delegates(address account) external view returns (address); 44 | 45 | /** 46 | * @dev Delegates votes from the sender to `delegatee`. 47 | */ 48 | function delegate(address delegatee) external; 49 | 50 | /** 51 | * @dev Delegates votes from signer to `delegatee`. 52 | */ 53 | function delegateBySig( 54 | address delegatee, 55 | uint256 nonce, 56 | uint256 expiry, 57 | uint8 v, 58 | bytes32 r, 59 | bytes32 s 60 | ) external; 61 | } 62 | -------------------------------------------------------------------------------- /src/starkware/isd/solidity/TimeLockedTokens.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0. 2 | pragma solidity ^0.8.16; 3 | 4 | import "starkware/isd/solidity/CommonConstants.sol"; 5 | import "starkware/isd/solidity/LockedTokenCommon.sol"; 6 | import "starkware/isd/third_party/open_zeppelin/utils/math/Math.sol"; 7 | 8 | /** 9 | This contract provides the number of unlocked tokens, 10 | and indicates if the grant has fully unlocked. 11 | */ 12 | abstract contract TimeLockedTokens { 13 | // The lockedCommon is the central contract that provisions the locked grants. 14 | // It also used to maintain the token global timelock. 15 | LockedTokenCommon immutable lockedCommon; 16 | 17 | // The grant start time. This is the start time of the grant 4 years gradual unlock. 18 | // Grant can be deployed with startTime in the past or in the future. 19 | // The range of allowed past/future spread is defined in {CommonConstants}. 20 | // and validated in the constructor. 21 | uint256 public immutable startTime; 22 | 23 | // The amount of tokens in the locked grant. 24 | uint256 public immutable grantAmount; 25 | 26 | constructor(uint256 grantAmount_, uint256 startTime_) { 27 | lockedCommon = LockedTokenCommon(msg.sender); 28 | grantAmount = grantAmount_; 29 | startTime = startTime_; 30 | } 31 | 32 | /* 33 | Indicates whether the grant has fully unlocked. 34 | */ 35 | function isGrantFullyUnlocked() public view returns (bool) { 36 | return block.timestamp >= startTime + GRANT_LOCKUP_PERIOD; 37 | } 38 | 39 | /* 40 | The number of locked tokens that were unlocked so far. 41 | */ 42 | function unlockedTokens() public view returns (uint256) { 43 | // Before globalUnlockTime passes, The entire grant is locked. 44 | if (block.timestamp <= lockedCommon.globalUnlockTime()) return 0; 45 | 46 | uint256 cappedElapsedTime = Math.min(elapsedTime(), GRANT_LOCKUP_PERIOD); 47 | return (grantAmount * cappedElapsedTime) / GRANT_LOCKUP_PERIOD; 48 | } 49 | 50 | /* 51 | Returns the time passed (in seconds) since grant start time. 52 | Returns 0 if start time is in the future. 53 | */ 54 | function elapsedTime() public view returns (uint256) { 55 | return block.timestamp > startTime ? block.timestamp - startTime : 0; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/token/ERC20/extensions/draft-IERC20Permit.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in 8 | * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. 9 | * 10 | * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by 11 | * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't 12 | * need to send a transaction, and thus is not required to hold Ether at all. 13 | */ 14 | interface IERC20Permit { 15 | /** 16 | * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, 17 | * given ``owner``'s signed approval. 18 | * 19 | * IMPORTANT: The same issues {IERC20-approve} has related to transaction 20 | * ordering also apply here. 21 | * 22 | * Emits an {Approval} event. 23 | * 24 | * Requirements: 25 | * 26 | * - `spender` cannot be the zero address. 27 | * - `deadline` must be a timestamp in the future. 28 | * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` 29 | * over the EIP712-formatted function arguments. 30 | * - the signature must use ``owner``'s current nonce (see {nonces}). 31 | * 32 | * For more information on the signature format, see the 33 | * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP 34 | * section]. 35 | */ 36 | function permit( 37 | address owner, 38 | address spender, 39 | uint256 value, 40 | uint256 deadline, 41 | uint8 v, 42 | bytes32 r, 43 | bytes32 s 44 | ) external; 45 | 46 | /** 47 | * @dev Returns the current nonce for `owner`. This value must be 48 | * included whenever a signature is generated for {permit}. 49 | * 50 | * Every successful call to {permit} increases ``owner``'s nonce by one. This 51 | * prevents a signature from being used multiple times. 52 | */ 53 | function nonces(address owner) external view returns (uint256); 54 | 55 | /** 56 | * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. 57 | */ 58 | // solhint-disable-next-line func-name-mixedcase 59 | function DOMAIN_SEPARATOR() external view returns (bytes32); 60 | } 61 | -------------------------------------------------------------------------------- /src/starkware/isd/solidity/GlobalUnlock.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0. 2 | pragma solidity ^0.8.16; 3 | 4 | import "starkware/isd/solidity/CommonConstants.sol"; 5 | import "starkware/isd/third_party/open_zeppelin/access/AccessControl.sol"; 6 | 7 | /** 8 | This contract handles the StarkNet Token global timelock. 9 | The Global Timelock is applied on all the locked token grants. 10 | Before the global timelock expires, all the locked token grants, are 100% locked, 11 | regardless of grant size and elapsed time since grant start time. 12 | Once the timelock expires, the amount of locked tokens in the grant is determined by the size 13 | of the grant and its start time. 14 | 15 | The global time-lock can be changed by an admin. To perform that, 16 | the admin must hold the GLOBAL_TIMELOCK_ADMIN_ROLE rights on the `LockedTokenCommon` contract. 17 | The global time-lock can be reset to a new timestamp as long as the following conditions are met: 18 | i. The new timestamp is in the future with at least a minimal margin. 19 | ii. The new timestamp does not exceed the global time-lock upper bound. 20 | iii. The global time-lock has not expired yet. 21 | 22 | The deployed LockedTokenGrant contracts query this contract to read the global timelock. 23 | */ 24 | abstract contract GlobalUnlock is AccessControl { 25 | uint256 internal immutable UPPER_LIMIT_GLOBAL_TIME_LOCK; 26 | uint256 public globalUnlockTime; 27 | 28 | event GlobalUnlockTimeUpdate( 29 | uint256 oldUnlockTime, 30 | uint256 newUnlockTime, 31 | address indexed sender 32 | ); 33 | 34 | constructor() { 35 | UPPER_LIMIT_GLOBAL_TIME_LOCK = block.timestamp + MAX_DURATION_GLOBAL_TIMELOCK; 36 | _updateGlobalLock(block.timestamp + DEFAULT_DURATION_GLOBAL_TIMELOCK); 37 | } 38 | 39 | function updateGlobalLock(uint256 unlockTime) external onlyRole(GLOBAL_TIMELOCK_ADMIN_ROLE) { 40 | require(unlockTime > block.timestamp + MIN_UNLOCK_DELAY, "SELECTED_TIME_TOO_EARLY"); 41 | require(unlockTime < UPPER_LIMIT_GLOBAL_TIME_LOCK, "SELECTED_TIME_EXCEED_LIMIT"); 42 | 43 | require(block.timestamp < globalUnlockTime, "GLOBAL_LOCK_ALREADY_EXPIRED"); 44 | _updateGlobalLock(unlockTime); 45 | } 46 | 47 | /* 48 | Setter for the globalUnlockTime. 49 | See caller function code for update logic, validation and restrictions. 50 | */ 51 | function _updateGlobalLock(uint256 newUnlockTime) internal { 52 | emit GlobalUnlockTimeUpdate(globalUnlockTime, newUnlockTime, msg.sender); 53 | globalUnlockTime = newUnlockTime; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/utils/Strings.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.7.0) (utils/Strings.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev String operations. 8 | */ 9 | library Strings { 10 | bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef"; 11 | uint8 private constant _ADDRESS_LENGTH = 20; 12 | 13 | /** 14 | * @dev Converts a `uint256` to its ASCII `string` decimal representation. 15 | */ 16 | function toString(uint256 value) internal pure returns (string memory) { 17 | // Inspired by OraclizeAPI's implementation - MIT licence 18 | // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol 19 | 20 | if (value == 0) { 21 | return "0"; 22 | } 23 | uint256 temp = value; 24 | uint256 digits; 25 | while (temp != 0) { 26 | digits++; 27 | temp /= 10; 28 | } 29 | bytes memory buffer = new bytes(digits); 30 | while (value != 0) { 31 | digits -= 1; 32 | buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); 33 | value /= 10; 34 | } 35 | return string(buffer); 36 | } 37 | 38 | /** 39 | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. 40 | */ 41 | function toHexString(uint256 value) internal pure returns (string memory) { 42 | if (value == 0) { 43 | return "0x00"; 44 | } 45 | uint256 temp = value; 46 | uint256 length = 0; 47 | while (temp != 0) { 48 | length++; 49 | temp >>= 8; 50 | } 51 | return toHexString(value, length); 52 | } 53 | 54 | /** 55 | * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. 56 | */ 57 | function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { 58 | bytes memory buffer = new bytes(2 * length + 2); 59 | buffer[0] = "0"; 60 | buffer[1] = "x"; 61 | for (uint256 i = 2 * length + 1; i > 1; --i) { 62 | buffer[i] = _HEX_SYMBOLS[value & 0xf]; 63 | value >>= 4; 64 | } 65 | require(value == 0, "Strings: hex length insufficient"); 66 | return string(buffer); 67 | } 68 | 69 | /** 70 | * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. 71 | */ 72 | function toHexString(address addr) internal pure returns (string memory) { 73 | return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/token/ERC20/IERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev Interface of the ERC20 standard as defined in the EIP. 8 | */ 9 | interface IERC20 { 10 | /** 11 | * @dev Emitted when `value` tokens are moved from one account (`from`) to 12 | * another (`to`). 13 | * 14 | * Note that `value` may be zero. 15 | */ 16 | event Transfer(address indexed from, address indexed to, uint256 value); 17 | 18 | /** 19 | * @dev Emitted when the allowance of a `spender` for an `owner` is set by 20 | * a call to {approve}. `value` is the new allowance. 21 | */ 22 | event Approval(address indexed owner, address indexed spender, uint256 value); 23 | 24 | /** 25 | * @dev Returns the amount of tokens in existence. 26 | */ 27 | function totalSupply() external view returns (uint256); 28 | 29 | /** 30 | * @dev Returns the amount of tokens owned by `account`. 31 | */ 32 | function balanceOf(address account) external view returns (uint256); 33 | 34 | /** 35 | * @dev Moves `amount` tokens from the caller's account to `to`. 36 | * 37 | * Returns a boolean value indicating whether the operation succeeded. 38 | * 39 | * Emits a {Transfer} event. 40 | */ 41 | function transfer(address to, uint256 amount) external returns (bool); 42 | 43 | /** 44 | * @dev Returns the remaining number of tokens that `spender` will be 45 | * allowed to spend on behalf of `owner` through {transferFrom}. This is 46 | * zero by default. 47 | * 48 | * This value changes when {approve} or {transferFrom} are called. 49 | */ 50 | function allowance(address owner, address spender) external view returns (uint256); 51 | 52 | /** 53 | * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 54 | * 55 | * Returns a boolean value indicating whether the operation succeeded. 56 | * 57 | * IMPORTANT: Beware that changing an allowance with this method brings the risk 58 | * that someone may use both the old and the new allowance by unfortunate 59 | * transaction ordering. One possible solution to mitigate this race 60 | * condition is to first reduce the spender's allowance to 0 and set the 61 | * desired value afterwards: 62 | * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 63 | * 64 | * Emits an {Approval} event. 65 | */ 66 | function approve(address spender, uint256 amount) external returns (bool); 67 | 68 | /** 69 | * @dev Moves `amount` tokens from `from` to `to` using the 70 | * allowance mechanism. `amount` is then deducted from the caller's 71 | * allowance. 72 | * 73 | * Returns a boolean value indicating whether the operation succeeded. 74 | * 75 | * Emits a {Transfer} event. 76 | */ 77 | function transferFrom( 78 | address from, 79 | address to, 80 | uint256 amount 81 | ) external returns (bool); 82 | } 83 | -------------------------------------------------------------------------------- /src/starkware/isd/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | python_lib(isd_token_sol 2 | PREFIX starkware/isd 3 | FILES 4 | solidity/StarkNetToken.sol 5 | third_party/open_zeppelin/access/AccessControl.sol 6 | third_party/open_zeppelin/access/IAccessControl.sol 7 | third_party/open_zeppelin/governance/utils/IVotes.sol 8 | third_party/open_zeppelin/token/ERC20/ERC20.sol 9 | third_party/open_zeppelin/token/ERC20/extensions/draft-ERC20Permit.sol 10 | third_party/open_zeppelin/token/ERC20/extensions/draft-IERC20Permit.sol 11 | third_party/open_zeppelin/token/ERC20/extensions/ERC20Votes.sol 12 | third_party/open_zeppelin/token/ERC20/extensions/IERC20Metadata.sol 13 | third_party/open_zeppelin/token/ERC20/IERC20.sol 14 | third_party/open_zeppelin/utils/Context.sol 15 | third_party/open_zeppelin/utils/Counters.sol 16 | third_party/open_zeppelin/utils/cryptography/draft-EIP712.sol 17 | third_party/open_zeppelin/utils/cryptography/ECDSA.sol 18 | third_party/open_zeppelin/utils/introspection/ERC165.sol 19 | third_party/open_zeppelin/utils/introspection/IERC165.sol 20 | third_party/open_zeppelin/utils/math/Math.sol 21 | third_party/open_zeppelin/utils/math/SafeCast.sol 22 | third_party/open_zeppelin/utils/Strings.sol 23 | LIBS 24 | ) 25 | 26 | solidity_env(isd_token_sol_env 27 | SOLC_BIN solc-0.8.16 28 | OPTIMIZE_RUNS 1000000 29 | CONTRACTS 30 | StarkNetToken 31 | LIBS 32 | isd_token_sol 33 | ) 34 | 35 | python_lib(isd_locked_token_sol 36 | PREFIX starkware/isd 37 | FILES 38 | solidity/TimeLockedTokens.sol 39 | solidity/CommonConstants.sol 40 | solidity/DelegationSupport.sol 41 | solidity/GlobalUnlock.sol 42 | solidity/LockedTokenCommon.sol 43 | solidity/LockedTokenGrant.sol 44 | third_party/open_zeppelin/access/AccessControl.sol 45 | third_party/open_zeppelin/access/IAccessControl.sol 46 | third_party/open_zeppelin/governance/utils/IVotes.sol 47 | third_party/open_zeppelin/token/ERC20/IERC20.sol 48 | third_party/open_zeppelin/utils/Address.sol 49 | third_party/open_zeppelin/utils/Context.sol 50 | third_party/open_zeppelin/utils/introspection/ERC165.sol 51 | third_party/open_zeppelin/utils/introspection/IERC165.sol 52 | third_party/open_zeppelin/utils/math/Math.sol 53 | third_party/open_zeppelin/utils/Strings.sol 54 | LIBS 55 | ) 56 | 57 | solidity_env(isd_locked_token_sol_env 58 | SOLC_BIN solc-0.8.16 59 | OPTIMIZE_RUNS 1000000 60 | CONTRACTS 61 | LockedTokenCommon 62 | LockedTokenGrant 63 | LIBS 64 | isd_locked_token_sol 65 | ) 66 | 67 | python_lib(isd_token_contracts_lib 68 | PREFIX starkware/isd 69 | FILES 70 | contracts.py 71 | 72 | LIBS 73 | starkware_contracts_utils_lib 74 | 75 | ARTIFACTS 76 | "${CMAKE_CURRENT_BINARY_DIR}/StakingContractStub.json solidity/StakingContractStub.json" 77 | "${CMAKE_CURRENT_BINARY_DIR}/StarkNetToken.json solidity/StarkNetToken.json" 78 | "${CMAKE_CURRENT_BINARY_DIR}/LockedTokenCommon.json solidity/LockedTokenCommon.json" 79 | "${CMAKE_CURRENT_BINARY_DIR}/LockedTokenGrant.json solidity/LockedTokenGrant.json" 80 | ) 81 | add_dependencies(isd_token_contracts_lib isd_token_sol_env isd_locked_token_sol_env) 82 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/access/IAccessControl.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev External interface of AccessControl declared to support ERC165 detection. 8 | */ 9 | interface IAccessControl { 10 | /** 11 | * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` 12 | * 13 | * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite 14 | * {RoleAdminChanged} not being emitted signaling this. 15 | * 16 | * _Available since v3.1._ 17 | */ 18 | event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); 19 | 20 | /** 21 | * @dev Emitted when `account` is granted `role`. 22 | * 23 | * `sender` is the account that originated the contract call, an admin role 24 | * bearer except when using {AccessControl-_setupRole}. 25 | */ 26 | event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); 27 | 28 | /** 29 | * @dev Emitted when `account` is revoked `role`. 30 | * 31 | * `sender` is the account that originated the contract call: 32 | * - if using `revokeRole`, it is the admin role bearer 33 | * - if using `renounceRole`, it is the role bearer (i.e. `account`) 34 | */ 35 | event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); 36 | 37 | /** 38 | * @dev Returns `true` if `account` has been granted `role`. 39 | */ 40 | function hasRole(bytes32 role, address account) external view returns (bool); 41 | 42 | /** 43 | * @dev Returns the admin role that controls `role`. See {grantRole} and 44 | * {revokeRole}. 45 | * 46 | * To change a role's admin, use {AccessControl-_setRoleAdmin}. 47 | */ 48 | function getRoleAdmin(bytes32 role) external view returns (bytes32); 49 | 50 | /** 51 | * @dev Grants `role` to `account`. 52 | * 53 | * If `account` had not been already granted `role`, emits a {RoleGranted} 54 | * event. 55 | * 56 | * Requirements: 57 | * 58 | * - the caller must have ``role``'s admin role. 59 | */ 60 | function grantRole(bytes32 role, address account) external; 61 | 62 | /** 63 | * @dev Revokes `role` from `account`. 64 | * 65 | * If `account` had been granted `role`, emits a {RoleRevoked} event. 66 | * 67 | * Requirements: 68 | * 69 | * - the caller must have ``role``'s admin role. 70 | */ 71 | function revokeRole(bytes32 role, address account) external; 72 | 73 | /** 74 | * @dev Revokes `role` from the calling account. 75 | * 76 | * Roles are often managed via {grantRole} and {revokeRole}: this function's 77 | * purpose is to provide a mechanism for accounts to lose their privileges 78 | * if they are compromised (such as when a trusted device is misplaced). 79 | * 80 | * If the calling account had been granted `role`, emits a {RoleRevoked} 81 | * event. 82 | * 83 | * Requirements: 84 | * 85 | * - the caller must be `account`. 86 | */ 87 | function renounceRole(bytes32 role, address account) external; 88 | } 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## StarkNet Token 2 | 3 | This repository contains the solidity files implementing the StarkNet token and related contracts. 4 | This repository and this README file do not relate to any other aspect of StarkNet or StarkNet Token. 5 | 6 | ### Introduction 7 | The __StarkNet Token__ is an ERC20 Solidity contract. 8 | 9 | #### Basic info 10 | Name: __StarkNet Token__ 11 | 12 | Symbol: __STRK__ 13 | 14 | Decimals: __18__ 15 | 16 | #### 17 | The StarkNet Token is a straightforward implementation of the OpenZeppelin reference code. 18 | 19 | The access control is following OpenZeppelin AccessControl: 20 | Privileged Roles : 21 | 1. DEFAULT_ADMIN_ROLE is an admin role for MINTER_ROLE 22 | 2. MINTER_ROLE: is allowed to mint. 23 | 24 | ### Locked tokens considerations ### 25 | The grants are locked for regulatory reasons. 26 | The lock is enforced by the {LockedTokenGrant} contract. 27 | 28 | Global unlock time is shared between all the grants. It's maintained by a centralized contract {LockedTokenCommon}. 29 | 30 | The {LockedTokenCommon} contract is also used to deploy the {LockedTokenGrant} and provide them with funds in an atomic manner. 31 | 32 | ### 1. Locked Token Grants 33 | - A Locked Token grant is a grant of locked tokens, granted to a recipient address. 34 | - They are deployed from `LockedTokenCommon` 35 | - The balance transferred to them is from an approved pool, not from the balance of the LockedTokenCommon itself. 36 | - LockedTokenGrant allows gradual release of tokens to the recipient address. 37 | A locked grant has the following properties: 38 | -- Start time - the start time when the release of the locked grant starts 39 | -- Grant amount - the amount of tokens in the grant. 40 | Once the grant start time passes, the locked tokens gradually release at a fixed rate, 41 | over a duration of 4 years. 42 | - A recipient address can receive up to 1 locked token grant. 43 | See _Global time-lock_ and _Exemption from lock_ for "modification" of this behavior. 44 | 45 | `LOCKED_GRANT_ADMIN_ROLE` is a role defined on the `LockedTokenCommon` contract. 46 | Account holding `LOCKED_GRANT_ADMIN_ROLE` permission can grant locked tokens. 47 | 48 | ### 2. Gradual Release 49 | The locked token grant releases gradually and evenly across 4 years 50 | starting from the grant start time. 51 | Before the grant start time, it's 100% locked. 52 | 53 | ### 3. Global time-lock 54 | The `LockedTokenCommon` maintains a global time-lock 55 | i.e. a common time-lock for all the grants that were allocated by this contract. 56 | Before the global time-lock expires - __ALL__ the locked token grants are __100%__ locked, 57 | __regardless__ of their start time. 58 | - The global time-lock can be changed by an admin. To perform that, 59 | the admin must hold the `GLOBAL_TIMELOCK_ADMIN_ROLE` rights on the `LockedTokenCommon` contract. 60 | - The global time-lock can be reset to a new timestamp as long as the following conditions are met: 61 | i. The new timestamp is in the future with at least a minimal margin. 62 | ii. The new timestamp does not exceed the global time-lock upper bound. 63 | iii. The global time-lock has not expired yet. 64 | 65 | ### 4. Exemption from lock 66 | Staking is exempted from locking. 67 | Exact mechanism for StarkNet Token staking is TBD. 68 | 69 | 70 | ### Repository structure: 71 | __src/starkware/isd/third_party__ : OpenZeppelin reference code (v4.7.3). 72 | 73 | __src/starkware/isd/solidity__ : StarkNet Token and related contracts solidity source files. 74 | 75 | ### Build instructions: 76 | `solc-0.8.16 --base-path src/ src/starkware/isd/solidity/StarkNetToken.sol --optimize-runs=1000000` 77 | 78 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/token/ERC20/extensions/draft-ERC20Permit.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/extensions/draft-ERC20Permit.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "./draft-IERC20Permit.sol"; 7 | import "../ERC20.sol"; 8 | import "../../../utils/cryptography/draft-EIP712.sol"; 9 | import "../../../utils/cryptography/ECDSA.sol"; 10 | import "../../../utils/Counters.sol"; 11 | 12 | /** 13 | * @dev Implementation of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in 14 | * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. 15 | * 16 | * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by 17 | * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't 18 | * need to send a transaction, and thus is not required to hold Ether at all. 19 | * 20 | * _Available since v3.4._ 21 | */ 22 | abstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 { 23 | using Counters for Counters.Counter; 24 | 25 | mapping(address => Counters.Counter) private _nonces; 26 | 27 | // solhint-disable-next-line var-name-mixedcase 28 | bytes32 private constant _PERMIT_TYPEHASH = 29 | keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); 30 | /** 31 | * @dev In previous versions `_PERMIT_TYPEHASH` was declared as `immutable`. 32 | * However, to ensure consistency with the upgradeable transpiler, we will continue 33 | * to reserve a slot. 34 | * @custom:oz-renamed-from _PERMIT_TYPEHASH 35 | */ 36 | // solhint-disable-next-line var-name-mixedcase 37 | bytes32 private _PERMIT_TYPEHASH_DEPRECATED_SLOT; 38 | 39 | /** 40 | * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `"1"`. 41 | * 42 | * It's a good idea to use the same `name` that is defined as the ERC20 token name. 43 | */ 44 | constructor(string memory name) EIP712(name, "1") {} 45 | 46 | /** 47 | * @dev See {IERC20Permit-permit}. 48 | */ 49 | function permit( 50 | address owner, 51 | address spender, 52 | uint256 value, 53 | uint256 deadline, 54 | uint8 v, 55 | bytes32 r, 56 | bytes32 s 57 | ) public virtual override { 58 | require(block.timestamp <= deadline, "ERC20Permit: expired deadline"); 59 | 60 | bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline)); 61 | 62 | bytes32 hash = _hashTypedDataV4(structHash); 63 | 64 | address signer = ECDSA.recover(hash, v, r, s); 65 | require(signer == owner, "ERC20Permit: invalid signature"); 66 | 67 | _approve(owner, spender, value); 68 | } 69 | 70 | /** 71 | * @dev See {IERC20Permit-nonces}. 72 | */ 73 | function nonces(address owner) public view virtual override returns (uint256) { 74 | return _nonces[owner].current(); 75 | } 76 | 77 | /** 78 | * @dev See {IERC20Permit-DOMAIN_SEPARATOR}. 79 | */ 80 | // solhint-disable-next-line func-name-mixedcase 81 | function DOMAIN_SEPARATOR() external view override returns (bytes32) { 82 | return _domainSeparatorV4(); 83 | } 84 | 85 | /** 86 | * @dev "Consume a nonce": return the current value and increment. 87 | * 88 | * _Available since v4.1._ 89 | */ 90 | function _useNonce(address owner) internal virtual returns (uint256 current) { 91 | Counters.Counter storage nonce = _nonces[owner]; 92 | current = nonce.current(); 93 | nonce.increment(); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/utils/cryptography/draft-EIP712.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "./ECDSA.sol"; 7 | 8 | /** 9 | * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data. 10 | * 11 | * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible, 12 | * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding 13 | * they need in their contracts using a combination of `abi.encode` and `keccak256`. 14 | * 15 | * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding 16 | * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA 17 | * ({_hashTypedDataV4}). 18 | * 19 | * The implementation of the domain separator was designed to be as efficient as possible while still properly updating 20 | * the chain id to protect against replay attacks on an eventual fork of the chain. 21 | * 22 | * NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method 23 | * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask]. 24 | * 25 | * _Available since v3.4._ 26 | */ 27 | abstract contract EIP712 { 28 | /* solhint-disable var-name-mixedcase */ 29 | // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to 30 | // invalidate the cached domain separator if the chain id changes. 31 | bytes32 private immutable _CACHED_DOMAIN_SEPARATOR; 32 | uint256 private immutable _CACHED_CHAIN_ID; 33 | address private immutable _CACHED_THIS; 34 | 35 | bytes32 private immutable _HASHED_NAME; 36 | bytes32 private immutable _HASHED_VERSION; 37 | bytes32 private immutable _TYPE_HASH; 38 | 39 | /* solhint-enable var-name-mixedcase */ 40 | 41 | /** 42 | * @dev Initializes the domain separator and parameter caches. 43 | * 44 | * The meaning of `name` and `version` is specified in 45 | * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: 46 | * 47 | * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. 48 | * - `version`: the current major version of the signing domain. 49 | * 50 | * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart 51 | * contract upgrade]. 52 | */ 53 | constructor(string memory name, string memory version) { 54 | bytes32 hashedName = keccak256(bytes(name)); 55 | bytes32 hashedVersion = keccak256(bytes(version)); 56 | bytes32 typeHash = keccak256( 57 | "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" 58 | ); 59 | _HASHED_NAME = hashedName; 60 | _HASHED_VERSION = hashedVersion; 61 | _CACHED_CHAIN_ID = block.chainid; 62 | _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion); 63 | _CACHED_THIS = address(this); 64 | _TYPE_HASH = typeHash; 65 | } 66 | 67 | /** 68 | * @dev Returns the domain separator for the current chain. 69 | */ 70 | function _domainSeparatorV4() internal view returns (bytes32) { 71 | if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) { 72 | return _CACHED_DOMAIN_SEPARATOR; 73 | } else { 74 | return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION); 75 | } 76 | } 77 | 78 | function _buildDomainSeparator( 79 | bytes32 typeHash, 80 | bytes32 nameHash, 81 | bytes32 versionHash 82 | ) private view returns (bytes32) { 83 | return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this))); 84 | } 85 | 86 | /** 87 | * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this 88 | * function returns the hash of the fully encoded EIP712 message for this domain. 89 | * 90 | * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: 91 | * 92 | * ```solidity 93 | * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( 94 | * keccak256("Mail(address to,string contents)"), 95 | * mailTo, 96 | * keccak256(bytes(mailContents)) 97 | * ))); 98 | * address signer = ECDSA.recover(digest, signature); 99 | * ``` 100 | */ 101 | function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) { 102 | return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash); 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /src/starkware/isd/solidity/LockedTokenCommon.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0. 2 | pragma solidity ^0.8.16; 3 | 4 | import "starkware/isd/solidity/GlobalUnlock.sol"; 5 | import "starkware/isd/solidity/LockedTokenGrant.sol"; 6 | import "starkware/isd/third_party/open_zeppelin/utils/Address.sol"; 7 | 8 | /** 9 | The {LockedTokenCommon} contract serves two purposes: 10 | 1. Maintain the StarkNetToken global timelock (see {GlobalUnlock}) 11 | 2. Allocate locked token grants in {LockedTokenGrant} contracts. 12 | 13 | Roles: 14 | ===== 15 | 1. At initializtion time, the msg.sender of the initialize tx, is defined as DEFAULT_ADMIN_ROLE. 16 | 2. LOCKED_GRANT_ADMIN_ROLE is required to call `grantLockedTokens`. 17 | 3. GLOBAL_TIMELOCK_ADMIN_ROLE is reqiured to call the `updateGlobalLock`. 18 | Two special roles must be granted 19 | 20 | Grant Locked Tokens: 21 | =================== 22 | Locked token grants are granted using the `grantLockedTokens` here. 23 | The arguments passed are: 24 | - recipient - The address of the tokens "owner". When the tokens get unlocked, they can be released 25 | to the recipient address, and only there. 26 | - amount - The number of tokens to be transfered onto the grant contract upon creation. 27 | - startTime - The timestamp of the beginning of the 4 years unlock period over which the tokens 28 | gradually unlock. The startTime can be anytime within the margins specified in the {CommonConstants}. 29 | - allocationPool - The {LockedTokenCommon} doesn't hold liquidity from which it can grant the tokens, 30 | but rather uses an external LP for that. The `allocationPool` is the address of the LP 31 | from which the tokens shall be allocated. The {LockedTokenCommon} must have sufficient allowance 32 | on the `allocationPool` so it can transfer funds from it onto the creatred grant contract. 33 | 34 | Flow: The {LockedTokenCommon} deploys the contract of the new {LockedTokenGrant}, 35 | transfer the grant amount from the allocationPool onto the new grant, 36 | and register the new grant in a mapping. 37 | */ 38 | contract LockedTokenCommon is GlobalUnlock { 39 | // Maps recipient to its locked grant contract. 40 | mapping(address => address) public grantByRecipient; 41 | IERC20 internal immutable tokenContract; 42 | address internal immutable stakingContract; 43 | address internal immutable defaultRegistry; 44 | 45 | event LockedTokenGranted( 46 | address indexed recipient, 47 | address indexed grantContract, 48 | uint256 grantAmount, 49 | uint256 startTime 50 | ); 51 | 52 | constructor( 53 | address tokenAddress_, 54 | address stakingContract_, 55 | address defaultRegistry_ 56 | ) { 57 | require(Address.isContract(tokenAddress_), "NOT_A_CONTRACT"); 58 | require(Address.isContract(stakingContract_), "NOT_A_CONTRACT"); 59 | require(Address.isContract(defaultRegistry_), "NOT_A_CONTRACT"); 60 | _grantRole(DEFAULT_ADMIN_ROLE, _msgSender()); 61 | tokenContract = IERC20(tokenAddress_); 62 | stakingContract = stakingContract_; 63 | defaultRegistry = defaultRegistry_; 64 | } 65 | 66 | /** 67 | Deploys a LockedTokenGrant and transfers `grantAmount` tokens onto it. 68 | Returns the address of the LockedTokenGrant contract. 69 | 70 | Tokens owned by the {LockedTokenGrant} are initially locked, and can only be used for staking. 71 | The tokens gradually unlocked and can be transferred to the `recipient`. 72 | */ 73 | function grantLockedTokens( 74 | address recipient, 75 | uint256 grantAmount, 76 | uint256 startTime, 77 | address allocationPool 78 | ) external onlyRole(LOCKED_GRANT_ADMIN_ROLE) returns (address) { 79 | require(grantByRecipient[recipient] == address(0x0), "ALREADY_GRANTED"); 80 | require( 81 | startTime < block.timestamp + LOCKED_GRANT_MAX_START_FUTURE_OFFSET, 82 | "START_TIME_TOO_LATE" 83 | ); 84 | require( 85 | startTime > block.timestamp - LOCKED_GRANT_MAX_START_PAST_OFFSET, 86 | "START_TIME_TOO_EARLY" 87 | ); 88 | 89 | address grantAddress = address( 90 | new LockedTokenGrant( 91 | address(tokenContract), 92 | stakingContract, 93 | defaultRegistry, 94 | recipient, 95 | grantAmount, 96 | startTime 97 | ) 98 | ); 99 | require( 100 | tokenContract.transferFrom(allocationPool, grantAddress, grantAmount), 101 | "TRANSFER_FROM_FAILED" 102 | ); 103 | grantByRecipient[recipient] = grantAddress; 104 | emit LockedTokenGranted(recipient, grantAddress, grantAmount, startTime); 105 | return grantAddress; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/starkware/isd/solidity/DelegationSupport.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0. 2 | pragma solidity ^0.8.16; 3 | 4 | import "starkware/isd/solidity/CommonConstants.sol"; 5 | import "starkware/isd/third_party/open_zeppelin/governance/utils/IVotes.sol"; 6 | 7 | /** 8 | A subset of the Gnosis DelegateRegistry ABI. 9 | */ 10 | interface IDelegateRegistry { 11 | function setDelegate(bytes32 id, address delegate) external; 12 | 13 | function delegation(address delegator, bytes32 id) external view returns (address); 14 | 15 | function clearDelegate(bytes32 id) external; 16 | } 17 | 18 | /** 19 | This contract implements the delegations made on behalf of the token grant contract. 20 | Two types of delegation are supported: 21 | 1. Delegation using Gnosis DelegateRegistry. 22 | 2. IVotes (Compound like) delegation, done directly on the ERC20 token. 23 | 24 | Upon construction, the {LockedTokenGrant} is provided with an address of the 25 | Gnosis DelegateRegistry. In addition, if a different DelegateRegistry is used, 26 | it can be passed in explicitly as an argument. 27 | 28 | Compound like vote delegation can be done on the StarkNet token, and on the Staking contract, 29 | assuming it will support that. 30 | */ 31 | abstract contract DelegationSupport { 32 | address public immutable recipient; 33 | 34 | // A Gnosis DelegateRegistry contract, provided by the common contract. 35 | // Used for delegation of votes, and also to permit token release and delegation actions. 36 | IDelegateRegistry public immutable defaultRegistry; 37 | 38 | // StarkNet Token. 39 | address public immutable token; 40 | 41 | // StarkNet Token Staking contract. 42 | address public immutable stakingContract; 43 | 44 | modifier onlyRecipient() { 45 | require(msg.sender == recipient, "ONLY_RECIPIENT"); 46 | _; 47 | } 48 | 49 | modifier onlyAllowedAgent(bytes32 agentId) { 50 | require( 51 | msg.sender == recipient || msg.sender == defaultRegistry.delegation(recipient, agentId), 52 | "ONLY_RECIPIENT_OR_APPROVED_AGENT" 53 | ); 54 | _; 55 | } 56 | 57 | constructor( 58 | address defaultRegistry_, 59 | address recipient_, 60 | address token_, 61 | address stakingContract_ 62 | ) { 63 | defaultRegistry = IDelegateRegistry(defaultRegistry_); 64 | recipient = recipient_; 65 | token = token_; 66 | stakingContract = stakingContract_; 67 | } 68 | 69 | /* 70 | Clears the {LockedTokenGrant} Gnosis delegation on the provided DelegateRegistry, 71 | for the ID provided. 72 | The call is restricted to the recipient or to the appointed delegation agent. 73 | */ 74 | function clearDelegate(bytes32 id, IDelegateRegistry registry) 75 | public 76 | onlyAllowedAgent(LOCKED_TOKEN_DELEGATION_AGENT) 77 | { 78 | registry.clearDelegate(id); 79 | } 80 | 81 | /* 82 | Sets the {LockedTokenGrant} Gnosis delegation on the provided DelegateRegistry, 83 | for the ID provided. 84 | The call is restricted to the recipient or to the appointed delegation agent. 85 | */ 86 | function setDelegate( 87 | bytes32 id, 88 | address delegate, 89 | IDelegateRegistry registry 90 | ) public onlyAllowedAgent(LOCKED_TOKEN_DELEGATION_AGENT) { 91 | registry.setDelegate(id, delegate); 92 | } 93 | 94 | /* 95 | Clears the {LockedTokenGrant} Gnosis delegation on the default DelegateRegistry, 96 | for the ID provided. 97 | The call is restricted to the recipient or to the appointed delegation agent. 98 | */ 99 | function clearDelegate(bytes32 id) external { 100 | clearDelegate(id, defaultRegistry); 101 | } 102 | 103 | /* 104 | Sets the {LockedTokenGrant} Gnosis delegation on the default DelegateRegistry, 105 | for the ID provided. 106 | The call is restricted to the recipient or to the appointed delegation agent. 107 | */ 108 | function setDelegate(bytes32 id, address delegate) external { 109 | setDelegate(id, delegate, defaultRegistry); 110 | } 111 | 112 | /* 113 | Sets the {LockedTokenGrant} IVotes delegation on the token. 114 | The call is restricted to the recipient or to the appointed delegation agent. 115 | */ 116 | function setDelegateOnToken(address delegatee) 117 | external 118 | onlyAllowedAgent(LOCKED_TOKEN_DELEGATION_AGENT) 119 | { 120 | _setIVotesDelegation(token, delegatee); 121 | } 122 | 123 | /* 124 | Sets the {LockedTokenGrant} IVotes delegation on the staking contract. 125 | The call is restricted to the recipient or to the appointed delegation agent. 126 | */ 127 | function setDelegateOnStaking(address delegatee) 128 | external 129 | onlyAllowedAgent(LOCKED_TOKEN_DELEGATION_AGENT) 130 | { 131 | _setIVotesDelegation(stakingContract, delegatee); 132 | } 133 | 134 | function _setIVotesDelegation(address target, address delegatee) private { 135 | IVotes(target).delegate(delegatee); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/starkware/isd/solidity/LockedTokenGrant.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0. 2 | pragma solidity ^0.8.16; 3 | 4 | import "starkware/isd/solidity/TimeLockedTokens.sol"; 5 | import "starkware/isd/solidity/CommonConstants.sol"; 6 | import "starkware/isd/solidity/DelegationSupport.sol"; 7 | import "starkware/isd/third_party/open_zeppelin/token/ERC20/IERC20.sol"; 8 | import "starkware/isd/third_party/open_zeppelin/utils/math/Math.sol"; 9 | 10 | /** 11 | This Contract holds a grant of locked tokens and gradually releases the tokens to its recipient. 12 | 13 | This contract should be deployed through the {LockedTokenCommon} contract, 14 | The global lock expiration time may be adjusted through the {LockedTokenCommon} contract. 15 | 16 | The {LockedTokenGrant} is initialized with the following parameters: 17 | `address token_`: The address of StarkNet token ERC20 contract. 18 | `address stakingContract_`: The address of the contrtact used for staking StarkNet token. 19 | `address defaultRegistry_`: Address of Gnosis DelegateRegistry. 20 | `address recipient_`: The owner of the grant. 21 | `uint256 grantAmount_`: The amount of tokens granted in this grant. 22 | `uint256 startTime`: The grant time-lock start timestamp. 23 | 24 | Token Gradual Release behavior: 25 | ============================== 26 | - Until the global timelock expires all the tokens are locked. 27 | - After the expiration of the global timelock tokens are gradually unlocked. 28 | - The amount of token unlocked is proportional to the time passed from startTime. 29 | - The grant is fully unlocked in 4 years. 30 | - to sum it up: 31 | ``` 32 | // 0 <= elapsedTime <= 4_YEARS 33 | elapsedTime = min(4_YEARS, max(0, currentTime - startTime)) 34 | unlocked = globalTimelockExpired ? grantAmount * (elapsedTime / 4_YEARS): 0; 35 | ``` 36 | - If the total balance of the grant address is larger than `grantAmount` - then the extra 37 | tokens on top of the grantAmount is available for release ONLY after the grant is fully 38 | unlocked. 39 | 40 | Global Time Lock: 41 | ================ 42 | StarkNet token has a global timelock. Before that timelock expires, all the tokens in the grant 43 | are fully locked. The global timelock can be modified post-deployment (to some extent). 44 | Therefore, the lock is maintained on a different contract that is centralized, and serves 45 | as a "timelock oracle" for all the {LockedTokenGrant} instances. I.e. whenever an instance of this 46 | contract needs to calculate the available tokens, it checks on the {LockedTokenCommon} contract 47 | if the global lock expired. See {LockedTokenCommon} for addtional details on the global timelock. 48 | 49 | Token Release Operation: 50 | ====================== 51 | - Tokens are owned by the `recipient`. They cannot be revoked. 52 | - At any given time the recipient can release any amount of tokens 53 | as long as the specified amount is available for release. 54 | - The amount of tokens available for release is the following: 55 | ``` 56 | availableAmount = min(token.balanceOf(this), (unlocked - alreadyReleased)); 57 | ``` 58 | The `min` is used here, because a part of the grant balance might be staked. 59 | - Only the recipient or an appointed {LOCKED_TOKEN_RELEASE_AGENT} are allowed to trigger 60 | release of tokens. 61 | - The released tokens can be transferred ONLY to the recipient address. 62 | 63 | Appointing agents for actions: 64 | ======================== 65 | Certain activities on this contract can be done not only by the grant recipient, but also by a delegate, 66 | appointed by the recipient. 67 | The delegation is done on a Gnosis DelegateRegistry contract, that was given to this contract 68 | in construction. The address of the {DelegateRegistry} is stored in the public variable named 69 | `defaultRegistry`. 70 | 1. The function `releaseTokens` can be called by the account (we use the term agent for this) whose address 71 | was delegated for this ID: 72 | 0x07238b05622b6f7e824800927d4f7786fca234153c28aeae2fa6fad5361ef6e7 [= keccak(text="LOCKED_TOKEN_RELEASE_AGENT")] 73 | 2. The functions `setDelegate` `clearDelegate` `setDelegationOnToken` `setDelegationOnStaking` can be called 74 | by the agent whose address was delegated for this ID: 75 | 0x477b64bf0d3f527eb7f7efeb334cf2ba231a93256d546759ad12a5add2734fb1 [= keccak(text="LOCKED_TOKEN_DELEGATION_AGENT")] 76 | 77 | Staking: 78 | ======= 79 | Staking of StarkNet tokens are exempted from the lock. I.e. Tokens from the locked grant 80 | can be staked, even up to the full grant amount, at any given time. 81 | However, the exect interface of the staking contract is not finalized yet. 82 | Therefore, the {LockedTokenGrant} way support staking is by a dedicated approval function `approveForStaking`. 83 | This function can be called only the recipient, and sets the allowace to the specified amount on the staking contract. 84 | This function is limited such that it approves only the staking contract, and no other address. 85 | The staking contract will support staking from a {LockedTokenGrant} using a dedicated API. 86 | 87 | Voting Delegation: 88 | ================= 89 | The {LockedTokenGrant} suports both Compound like delegation and delegation using Gnosis DelegateRegistry. 90 | These functions set the delegation of the Grant address (the address of the grant contract). 91 | Only the recipient and a LOCKED_TOKEN_DELEGATION_AGENT (if appointed) can call these functions. 92 | */ 93 | contract LockedTokenGrant is TimeLockedTokens, DelegationSupport { 94 | uint256 public releasedTokens; 95 | 96 | event TokensSentToRecipient( 97 | address indexed recipient, 98 | address indexed grantContract, 99 | uint256 amountSent, 100 | uint256 aggregateSent 101 | ); 102 | 103 | event TokenAllowanceForStaking( 104 | address indexed grantContract, 105 | address indexed stakingContract, 106 | uint256 allowanceSet 107 | ); 108 | 109 | constructor( 110 | address token_, 111 | address stakingContract_, 112 | address defaultRegistry_, 113 | address recipient_, 114 | uint256 grantAmount_, 115 | uint256 startTime_ 116 | ) 117 | DelegationSupport(defaultRegistry_, recipient_, address(token_), stakingContract_) 118 | TimeLockedTokens(grantAmount_, startTime_) 119 | {} 120 | 121 | /* 122 | Returns the available tokens for release. 123 | Once the grant lock is fully expired - the entire balance is always available. 124 | Until then, only the relative part of the grant grantAmount is available. 125 | However, given staking, the actual balance may be smaller. 126 | Note that any excessive tokens (beyond grantAmount) transferred to this contract 127 | are going to be locked until the grant lock fully expires. 128 | */ 129 | function availableTokens() public view returns (uint256) { 130 | uint256 currentBalance = IERC20(token).balanceOf(address(this)); 131 | return 132 | isGrantFullyUnlocked() 133 | ? currentBalance 134 | : Math.min(currentBalance, (unlockedTokens() - releasedTokens)); 135 | } 136 | 137 | /* 138 | Transfers `requestedAmount` tokens (if available) to the `recipient`. 139 | */ 140 | function releaseTokens(uint256 requestedAmount) 141 | external 142 | onlyAllowedAgent(LOCKED_TOKEN_RELEASE_AGENT) 143 | { 144 | require(requestedAmount <= availableTokens(), "REQUESTED_AMOUNT_UNAVAILABLE"); 145 | releasedTokens += requestedAmount; 146 | IERC20(token).transfer(recipient, requestedAmount); 147 | emit TokensSentToRecipient(recipient, address(this), requestedAmount, releasedTokens); 148 | } 149 | 150 | /* 151 | Sets the allowance of the staking contract address to `approvedAmount`. 152 | to allow staking up to that amount of tokens. 153 | */ 154 | function approveForStaking(uint256 approvedAmount) external onlyRecipient { 155 | IERC20(token).approve(stakingContract, approvedAmount); 156 | emit TokenAllowanceForStaking(address(this), stakingContract, approvedAmount); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/access/AccessControl.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.7.0) (access/AccessControl.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "./IAccessControl.sol"; 7 | import "../utils/Context.sol"; 8 | import "../utils/Strings.sol"; 9 | import "../utils/introspection/ERC165.sol"; 10 | 11 | /** 12 | * @dev Contract module that allows children to implement role-based access 13 | * control mechanisms. This is a lightweight version that doesn't allow enumerating role 14 | * members except through off-chain means by accessing the contract event logs. Some 15 | * applications may benefit from on-chain enumerability, for those cases see 16 | * {AccessControlEnumerable}. 17 | * 18 | * Roles are referred to by their `bytes32` identifier. These should be exposed 19 | * in the external API and be unique. The best way to achieve this is by 20 | * using `public constant` hash digests: 21 | * 22 | * ``` 23 | * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); 24 | * ``` 25 | * 26 | * Roles can be used to represent a set of permissions. To restrict access to a 27 | * function call, use {hasRole}: 28 | * 29 | * ``` 30 | * function foo() public { 31 | * require(hasRole(MY_ROLE, msg.sender)); 32 | * ... 33 | * } 34 | * ``` 35 | * 36 | * Roles can be granted and revoked dynamically via the {grantRole} and 37 | * {revokeRole} functions. Each role has an associated admin role, and only 38 | * accounts that have a role's admin role can call {grantRole} and {revokeRole}. 39 | * 40 | * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means 41 | * that only accounts with this role will be able to grant or revoke other 42 | * roles. More complex role relationships can be created by using 43 | * {_setRoleAdmin}. 44 | * 45 | * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to 46 | * grant and revoke this role. Extra precautions should be taken to secure 47 | * accounts that have been granted it. 48 | */ 49 | abstract contract AccessControl is Context, IAccessControl, ERC165 { 50 | struct RoleData { 51 | mapping(address => bool) members; 52 | bytes32 adminRole; 53 | } 54 | 55 | mapping(bytes32 => RoleData) private _roles; 56 | 57 | bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; 58 | 59 | /** 60 | * @dev Modifier that checks that an account has a specific role. Reverts 61 | * with a standardized message including the required role. 62 | * 63 | * The format of the revert reason is given by the following regular expression: 64 | * 65 | * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ 66 | * 67 | * _Available since v4.1._ 68 | */ 69 | modifier onlyRole(bytes32 role) { 70 | _checkRole(role); 71 | _; 72 | } 73 | 74 | /** 75 | * @dev See {IERC165-supportsInterface}. 76 | */ 77 | function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { 78 | return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); 79 | } 80 | 81 | /** 82 | * @dev Returns `true` if `account` has been granted `role`. 83 | */ 84 | function hasRole(bytes32 role, address account) public view virtual override returns (bool) { 85 | return _roles[role].members[account]; 86 | } 87 | 88 | /** 89 | * @dev Revert with a standard message if `_msgSender()` is missing `role`. 90 | * Overriding this function changes the behavior of the {onlyRole} modifier. 91 | * 92 | * Format of the revert message is described in {_checkRole}. 93 | * 94 | * _Available since v4.6._ 95 | */ 96 | function _checkRole(bytes32 role) internal view virtual { 97 | _checkRole(role, _msgSender()); 98 | } 99 | 100 | /** 101 | * @dev Revert with a standard message if `account` is missing `role`. 102 | * 103 | * The format of the revert reason is given by the following regular expression: 104 | * 105 | * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ 106 | */ 107 | function _checkRole(bytes32 role, address account) internal view virtual { 108 | if (!hasRole(role, account)) { 109 | revert( 110 | string( 111 | abi.encodePacked( 112 | "AccessControl: account ", 113 | Strings.toHexString(uint160(account), 20), 114 | " is missing role ", 115 | Strings.toHexString(uint256(role), 32) 116 | ) 117 | ) 118 | ); 119 | } 120 | } 121 | 122 | /** 123 | * @dev Returns the admin role that controls `role`. See {grantRole} and 124 | * {revokeRole}. 125 | * 126 | * To change a role's admin, use {_setRoleAdmin}. 127 | */ 128 | function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { 129 | return _roles[role].adminRole; 130 | } 131 | 132 | /** 133 | * @dev Grants `role` to `account`. 134 | * 135 | * If `account` had not been already granted `role`, emits a {RoleGranted} 136 | * event. 137 | * 138 | * Requirements: 139 | * 140 | * - the caller must have ``role``'s admin role. 141 | * 142 | * May emit a {RoleGranted} event. 143 | */ 144 | function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { 145 | _grantRole(role, account); 146 | } 147 | 148 | /** 149 | * @dev Revokes `role` from `account`. 150 | * 151 | * If `account` had been granted `role`, emits a {RoleRevoked} event. 152 | * 153 | * Requirements: 154 | * 155 | * - the caller must have ``role``'s admin role. 156 | * 157 | * May emit a {RoleRevoked} event. 158 | */ 159 | function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { 160 | _revokeRole(role, account); 161 | } 162 | 163 | /** 164 | * @dev Revokes `role` from the calling account. 165 | * 166 | * Roles are often managed via {grantRole} and {revokeRole}: this function's 167 | * purpose is to provide a mechanism for accounts to lose their privileges 168 | * if they are compromised (such as when a trusted device is misplaced). 169 | * 170 | * If the calling account had been revoked `role`, emits a {RoleRevoked} 171 | * event. 172 | * 173 | * Requirements: 174 | * 175 | * - the caller must be `account`. 176 | * 177 | * May emit a {RoleRevoked} event. 178 | */ 179 | function renounceRole(bytes32 role, address account) public virtual override { 180 | require(account == _msgSender(), "AccessControl: can only renounce roles for self"); 181 | 182 | _revokeRole(role, account); 183 | } 184 | 185 | /** 186 | * @dev Grants `role` to `account`. 187 | * 188 | * If `account` had not been already granted `role`, emits a {RoleGranted} 189 | * event. Note that unlike {grantRole}, this function doesn't perform any 190 | * checks on the calling account. 191 | * 192 | * May emit a {RoleGranted} event. 193 | * 194 | * [WARNING] 195 | * ==== 196 | * This function should only be called from the constructor when setting 197 | * up the initial roles for the system. 198 | * 199 | * Using this function in any other way is effectively circumventing the admin 200 | * system imposed by {AccessControl}. 201 | * ==== 202 | * 203 | * NOTE: This function is deprecated in favor of {_grantRole}. 204 | */ 205 | function _setupRole(bytes32 role, address account) internal virtual { 206 | _grantRole(role, account); 207 | } 208 | 209 | /** 210 | * @dev Sets `adminRole` as ``role``'s admin role. 211 | * 212 | * Emits a {RoleAdminChanged} event. 213 | */ 214 | function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { 215 | bytes32 previousAdminRole = getRoleAdmin(role); 216 | _roles[role].adminRole = adminRole; 217 | emit RoleAdminChanged(role, previousAdminRole, adminRole); 218 | } 219 | 220 | /** 221 | * @dev Grants `role` to `account`. 222 | * 223 | * Internal function without access restriction. 224 | * 225 | * May emit a {RoleGranted} event. 226 | */ 227 | function _grantRole(bytes32 role, address account) internal virtual { 228 | if (!hasRole(role, account)) { 229 | _roles[role].members[account] = true; 230 | emit RoleGranted(role, account, _msgSender()); 231 | } 232 | } 233 | 234 | /** 235 | * @dev Revokes `role` from `account`. 236 | * 237 | * Internal function without access restriction. 238 | * 239 | * May emit a {RoleRevoked} event. 240 | */ 241 | function _revokeRole(bytes32 role, address account) internal virtual { 242 | if (hasRole(role, account)) { 243 | _roles[role].members[account] = false; 244 | emit RoleRevoked(role, account, _msgSender()); 245 | } 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/utils/Address.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.7.0) (utils/Address.sol) 3 | 4 | pragma solidity ^0.8.1; 5 | 6 | /** 7 | * @dev Collection of functions related to the address type 8 | */ 9 | library Address { 10 | /** 11 | * @dev Returns true if `account` is a contract. 12 | * 13 | * [IMPORTANT] 14 | * ==== 15 | * It is unsafe to assume that an address for which this function returns 16 | * false is an externally-owned account (EOA) and not a contract. 17 | * 18 | * Among others, `isContract` will return false for the following 19 | * types of addresses: 20 | * 21 | * - an externally-owned account 22 | * - a contract in construction 23 | * - an address where a contract will be created 24 | * - an address where a contract lived, but was destroyed 25 | * ==== 26 | * 27 | * [IMPORTANT] 28 | * ==== 29 | * You shouldn't rely on `isContract` to protect against flash loan attacks! 30 | * 31 | * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets 32 | * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract 33 | * constructor. 34 | * ==== 35 | */ 36 | function isContract(address account) internal view returns (bool) { 37 | // This method relies on extcodesize/address.code.length, which returns 0 38 | // for contracts in construction, since the code is only stored at the end 39 | // of the constructor execution. 40 | 41 | return account.code.length > 0; 42 | } 43 | 44 | /** 45 | * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 46 | * `recipient`, forwarding all available gas and reverting on errors. 47 | * 48 | * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 49 | * of certain opcodes, possibly making contracts go over the 2300 gas limit 50 | * imposed by `transfer`, making them unable to receive funds via 51 | * `transfer`. {sendValue} removes this limitation. 52 | * 53 | * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 54 | * 55 | * IMPORTANT: because control is transferred to `recipient`, care must be 56 | * taken to not create reentrancy vulnerabilities. Consider using 57 | * {ReentrancyGuard} or the 58 | * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 59 | */ 60 | function sendValue(address payable recipient, uint256 amount) internal { 61 | require(address(this).balance >= amount, "Address: insufficient balance"); 62 | 63 | (bool success, ) = recipient.call{value: amount}(""); 64 | require(success, "Address: unable to send value, recipient may have reverted"); 65 | } 66 | 67 | /** 68 | * @dev Performs a Solidity function call using a low level `call`. A 69 | * plain `call` is an unsafe replacement for a function call: use this 70 | * function instead. 71 | * 72 | * If `target` reverts with a revert reason, it is bubbled up by this 73 | * function (like regular Solidity function calls). 74 | * 75 | * Returns the raw returned data. To convert to the expected return value, 76 | * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 77 | * 78 | * Requirements: 79 | * 80 | * - `target` must be a contract. 81 | * - calling `target` with `data` must not revert. 82 | * 83 | * _Available since v3.1._ 84 | */ 85 | function functionCall(address target, bytes memory data) internal returns (bytes memory) { 86 | return functionCall(target, data, "Address: low-level call failed"); 87 | } 88 | 89 | /** 90 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 91 | * `errorMessage` as a fallback revert reason when `target` reverts. 92 | * 93 | * _Available since v3.1._ 94 | */ 95 | function functionCall( 96 | address target, 97 | bytes memory data, 98 | string memory errorMessage 99 | ) internal returns (bytes memory) { 100 | return functionCallWithValue(target, data, 0, errorMessage); 101 | } 102 | 103 | /** 104 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 105 | * but also transferring `value` wei to `target`. 106 | * 107 | * Requirements: 108 | * 109 | * - the calling contract must have an ETH balance of at least `value`. 110 | * - the called Solidity function must be `payable`. 111 | * 112 | * _Available since v3.1._ 113 | */ 114 | function functionCallWithValue( 115 | address target, 116 | bytes memory data, 117 | uint256 value 118 | ) internal returns (bytes memory) { 119 | return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 120 | } 121 | 122 | /** 123 | * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 124 | * with `errorMessage` as a fallback revert reason when `target` reverts. 125 | * 126 | * _Available since v3.1._ 127 | */ 128 | function functionCallWithValue( 129 | address target, 130 | bytes memory data, 131 | uint256 value, 132 | string memory errorMessage 133 | ) internal returns (bytes memory) { 134 | require(address(this).balance >= value, "Address: insufficient balance for call"); 135 | require(isContract(target), "Address: call to non-contract"); 136 | 137 | (bool success, bytes memory returndata) = target.call{value: value}(data); 138 | return verifyCallResult(success, returndata, errorMessage); 139 | } 140 | 141 | /** 142 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 143 | * but performing a static call. 144 | * 145 | * _Available since v3.3._ 146 | */ 147 | function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { 148 | return functionStaticCall(target, data, "Address: low-level static call failed"); 149 | } 150 | 151 | /** 152 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 153 | * but performing a static call. 154 | * 155 | * _Available since v3.3._ 156 | */ 157 | function functionStaticCall( 158 | address target, 159 | bytes memory data, 160 | string memory errorMessage 161 | ) internal view returns (bytes memory) { 162 | require(isContract(target), "Address: static call to non-contract"); 163 | 164 | (bool success, bytes memory returndata) = target.staticcall(data); 165 | return verifyCallResult(success, returndata, errorMessage); 166 | } 167 | 168 | /** 169 | * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 170 | * but performing a delegate call. 171 | * 172 | * _Available since v3.4._ 173 | */ 174 | function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { 175 | return functionDelegateCall(target, data, "Address: low-level delegate call failed"); 176 | } 177 | 178 | /** 179 | * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], 180 | * but performing a delegate call. 181 | * 182 | * _Available since v3.4._ 183 | */ 184 | function functionDelegateCall( 185 | address target, 186 | bytes memory data, 187 | string memory errorMessage 188 | ) internal returns (bytes memory) { 189 | require(isContract(target), "Address: delegate call to non-contract"); 190 | 191 | (bool success, bytes memory returndata) = target.delegatecall(data); 192 | return verifyCallResult(success, returndata, errorMessage); 193 | } 194 | 195 | /** 196 | * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the 197 | * revert reason using the provided one. 198 | * 199 | * _Available since v4.3._ 200 | */ 201 | function verifyCallResult( 202 | bool success, 203 | bytes memory returndata, 204 | string memory errorMessage 205 | ) internal pure returns (bytes memory) { 206 | if (success) { 207 | return returndata; 208 | } else { 209 | // Look for revert reason and bubble it up if present 210 | if (returndata.length > 0) { 211 | // The easiest way to bubble the revert reason is using memory via assembly 212 | /// @solidity memory-safe-assembly 213 | assembly { 214 | let returndata_size := mload(returndata) 215 | revert(add(32, returndata), returndata_size) 216 | } 217 | } else { 218 | revert(errorMessage); 219 | } 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/utils/cryptography/ECDSA.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.7.3) (utils/cryptography/ECDSA.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "../Strings.sol"; 7 | 8 | /** 9 | * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. 10 | * 11 | * These functions can be used to verify that a message was signed by the holder 12 | * of the private keys of a given address. 13 | */ 14 | library ECDSA { 15 | enum RecoverError { 16 | NoError, 17 | InvalidSignature, 18 | InvalidSignatureLength, 19 | InvalidSignatureS, 20 | InvalidSignatureV 21 | } 22 | 23 | function _throwError(RecoverError error) private pure { 24 | if (error == RecoverError.NoError) { 25 | return; // no error: do nothing 26 | } else if (error == RecoverError.InvalidSignature) { 27 | revert("ECDSA: invalid signature"); 28 | } else if (error == RecoverError.InvalidSignatureLength) { 29 | revert("ECDSA: invalid signature length"); 30 | } else if (error == RecoverError.InvalidSignatureS) { 31 | revert("ECDSA: invalid signature 's' value"); 32 | } else if (error == RecoverError.InvalidSignatureV) { 33 | revert("ECDSA: invalid signature 'v' value"); 34 | } 35 | } 36 | 37 | /** 38 | * @dev Returns the address that signed a hashed message (`hash`) with 39 | * `signature` or error string. This address can then be used for verification purposes. 40 | * 41 | * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: 42 | * this function rejects them by requiring the `s` value to be in the lower 43 | * half order, and the `v` value to be either 27 or 28. 44 | * 45 | * IMPORTANT: `hash` _must_ be the result of a hash operation for the 46 | * verification to be secure: it is possible to craft signatures that 47 | * recover to arbitrary addresses for non-hashed data. A safe way to ensure 48 | * this is by receiving a hash of the original message (which may otherwise 49 | * be too long), and then calling {toEthSignedMessageHash} on it. 50 | * 51 | * Documentation for signature generation: 52 | * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] 53 | * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] 54 | * 55 | * _Available since v4.3._ 56 | */ 57 | function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { 58 | if (signature.length == 65) { 59 | bytes32 r; 60 | bytes32 s; 61 | uint8 v; 62 | // ecrecover takes the signature parameters, and the only way to get them 63 | // currently is to use assembly. 64 | /// @solidity memory-safe-assembly 65 | assembly { 66 | r := mload(add(signature, 0x20)) 67 | s := mload(add(signature, 0x40)) 68 | v := byte(0, mload(add(signature, 0x60))) 69 | } 70 | return tryRecover(hash, v, r, s); 71 | } else { 72 | return (address(0), RecoverError.InvalidSignatureLength); 73 | } 74 | } 75 | 76 | /** 77 | * @dev Returns the address that signed a hashed message (`hash`) with 78 | * `signature`. This address can then be used for verification purposes. 79 | * 80 | * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: 81 | * this function rejects them by requiring the `s` value to be in the lower 82 | * half order, and the `v` value to be either 27 or 28. 83 | * 84 | * IMPORTANT: `hash` _must_ be the result of a hash operation for the 85 | * verification to be secure: it is possible to craft signatures that 86 | * recover to arbitrary addresses for non-hashed data. A safe way to ensure 87 | * this is by receiving a hash of the original message (which may otherwise 88 | * be too long), and then calling {toEthSignedMessageHash} on it. 89 | */ 90 | function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { 91 | (address recovered, RecoverError error) = tryRecover(hash, signature); 92 | _throwError(error); 93 | return recovered; 94 | } 95 | 96 | /** 97 | * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. 98 | * 99 | * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] 100 | * 101 | * _Available since v4.3._ 102 | */ 103 | function tryRecover( 104 | bytes32 hash, 105 | bytes32 r, 106 | bytes32 vs 107 | ) internal pure returns (address, RecoverError) { 108 | bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 109 | uint8 v = uint8((uint256(vs) >> 255) + 27); 110 | return tryRecover(hash, v, r, s); 111 | } 112 | 113 | /** 114 | * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. 115 | * 116 | * _Available since v4.2._ 117 | */ 118 | function recover( 119 | bytes32 hash, 120 | bytes32 r, 121 | bytes32 vs 122 | ) internal pure returns (address) { 123 | (address recovered, RecoverError error) = tryRecover(hash, r, vs); 124 | _throwError(error); 125 | return recovered; 126 | } 127 | 128 | /** 129 | * @dev Overload of {ECDSA-tryRecover} that receives the `v`, 130 | * `r` and `s` signature fields separately. 131 | * 132 | * _Available since v4.3._ 133 | */ 134 | function tryRecover( 135 | bytes32 hash, 136 | uint8 v, 137 | bytes32 r, 138 | bytes32 s 139 | ) internal pure returns (address, RecoverError) { 140 | // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature 141 | // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines 142 | // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most 143 | // signatures from current libraries generate a unique signature with an s-value in the lower half order. 144 | // 145 | // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value 146 | // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or 147 | // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept 148 | // these malleable signatures as well. 149 | if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { 150 | return (address(0), RecoverError.InvalidSignatureS); 151 | } 152 | if (v != 27 && v != 28) { 153 | return (address(0), RecoverError.InvalidSignatureV); 154 | } 155 | 156 | // If the signature is valid (and not malleable), return the signer address 157 | address signer = ecrecover(hash, v, r, s); 158 | if (signer == address(0)) { 159 | return (address(0), RecoverError.InvalidSignature); 160 | } 161 | 162 | return (signer, RecoverError.NoError); 163 | } 164 | 165 | /** 166 | * @dev Overload of {ECDSA-recover} that receives the `v`, 167 | * `r` and `s` signature fields separately. 168 | */ 169 | function recover( 170 | bytes32 hash, 171 | uint8 v, 172 | bytes32 r, 173 | bytes32 s 174 | ) internal pure returns (address) { 175 | (address recovered, RecoverError error) = tryRecover(hash, v, r, s); 176 | _throwError(error); 177 | return recovered; 178 | } 179 | 180 | /** 181 | * @dev Returns an Ethereum Signed Message, created from a `hash`. This 182 | * produces hash corresponding to the one signed with the 183 | * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] 184 | * JSON-RPC method as part of EIP-191. 185 | * 186 | * See {recover}. 187 | */ 188 | function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) { 189 | // 32 is the length in bytes of hash, 190 | // enforced by the type signature above 191 | return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); 192 | } 193 | 194 | /** 195 | * @dev Returns an Ethereum Signed Message, created from `s`. This 196 | * produces hash corresponding to the one signed with the 197 | * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] 198 | * JSON-RPC method as part of EIP-191. 199 | * 200 | * See {recover}. 201 | */ 202 | function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { 203 | return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); 204 | } 205 | 206 | /** 207 | * @dev Returns an Ethereum Signed Typed Data, created from a 208 | * `domainSeparator` and a `structHash`. This produces hash corresponding 209 | * to the one signed with the 210 | * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] 211 | * JSON-RPC method as part of EIP-712. 212 | * 213 | * See {recover}. 214 | */ 215 | function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) { 216 | return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); 217 | } 218 | } 219 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/utils/math/Math.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/Math.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev Standard math utilities missing in the Solidity language. 8 | */ 9 | library Math { 10 | enum Rounding { 11 | Down, // Toward negative infinity 12 | Up, // Toward infinity 13 | Zero // Toward zero 14 | } 15 | 16 | /** 17 | * @dev Returns the largest of two numbers. 18 | */ 19 | function max(uint256 a, uint256 b) internal pure returns (uint256) { 20 | return a >= b ? a : b; 21 | } 22 | 23 | /** 24 | * @dev Returns the smallest of two numbers. 25 | */ 26 | function min(uint256 a, uint256 b) internal pure returns (uint256) { 27 | return a < b ? a : b; 28 | } 29 | 30 | /** 31 | * @dev Returns the average of two numbers. The result is rounded towards 32 | * zero. 33 | */ 34 | function average(uint256 a, uint256 b) internal pure returns (uint256) { 35 | // (a + b) / 2 can overflow. 36 | return (a & b) + (a ^ b) / 2; 37 | } 38 | 39 | /** 40 | * @dev Returns the ceiling of the division of two numbers. 41 | * 42 | * This differs from standard division with `/` in that it rounds up instead 43 | * of rounding down. 44 | */ 45 | function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { 46 | // (a + b - 1) / b can overflow on addition, so we distribute. 47 | return a == 0 ? 0 : (a - 1) / b + 1; 48 | } 49 | 50 | /** 51 | * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 52 | * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) 53 | * with further edits by Uniswap Labs also under MIT license. 54 | */ 55 | function mulDiv( 56 | uint256 x, 57 | uint256 y, 58 | uint256 denominator 59 | ) internal pure returns (uint256 result) { 60 | unchecked { 61 | // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use 62 | // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 63 | // variables such that product = prod1 * 2^256 + prod0. 64 | uint256 prod0; // Least significant 256 bits of the product 65 | uint256 prod1; // Most significant 256 bits of the product 66 | assembly { 67 | let mm := mulmod(x, y, not(0)) 68 | prod0 := mul(x, y) 69 | prod1 := sub(sub(mm, prod0), lt(mm, prod0)) 70 | } 71 | 72 | // Handle non-overflow cases, 256 by 256 division. 73 | if (prod1 == 0) { 74 | return prod0 / denominator; 75 | } 76 | 77 | // Make sure the result is less than 2^256. Also prevents denominator == 0. 78 | require(denominator > prod1); 79 | 80 | /////////////////////////////////////////////// 81 | // 512 by 256 division. 82 | /////////////////////////////////////////////// 83 | 84 | // Make division exact by subtracting the remainder from [prod1 prod0]. 85 | uint256 remainder; 86 | assembly { 87 | // Compute remainder using mulmod. 88 | remainder := mulmod(x, y, denominator) 89 | 90 | // Subtract 256 bit number from 512 bit number. 91 | prod1 := sub(prod1, gt(remainder, prod0)) 92 | prod0 := sub(prod0, remainder) 93 | } 94 | 95 | // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. 96 | // See https://cs.stackexchange.com/q/138556/92363. 97 | 98 | // Does not overflow because the denominator cannot be zero at this stage in the function. 99 | uint256 twos = denominator & (~denominator + 1); 100 | assembly { 101 | // Divide denominator by twos. 102 | denominator := div(denominator, twos) 103 | 104 | // Divide [prod1 prod0] by twos. 105 | prod0 := div(prod0, twos) 106 | 107 | // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. 108 | twos := add(div(sub(0, twos), twos), 1) 109 | } 110 | 111 | // Shift in bits from prod1 into prod0. 112 | prod0 |= prod1 * twos; 113 | 114 | // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such 115 | // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for 116 | // four bits. That is, denominator * inv = 1 mod 2^4. 117 | uint256 inverse = (3 * denominator) ^ 2; 118 | 119 | // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works 120 | // in modular arithmetic, doubling the correct bits in each step. 121 | inverse *= 2 - denominator * inverse; // inverse mod 2^8 122 | inverse *= 2 - denominator * inverse; // inverse mod 2^16 123 | inverse *= 2 - denominator * inverse; // inverse mod 2^32 124 | inverse *= 2 - denominator * inverse; // inverse mod 2^64 125 | inverse *= 2 - denominator * inverse; // inverse mod 2^128 126 | inverse *= 2 - denominator * inverse; // inverse mod 2^256 127 | 128 | // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. 129 | // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is 130 | // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 131 | // is no longer required. 132 | result = prod0 * inverse; 133 | return result; 134 | } 135 | } 136 | 137 | /** 138 | * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. 139 | */ 140 | function mulDiv( 141 | uint256 x, 142 | uint256 y, 143 | uint256 denominator, 144 | Rounding rounding 145 | ) internal pure returns (uint256) { 146 | uint256 result = mulDiv(x, y, denominator); 147 | if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { 148 | result += 1; 149 | } 150 | return result; 151 | } 152 | 153 | /** 154 | * @dev Returns the square root of a number. It the number is not a perfect square, the value is rounded down. 155 | * 156 | * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). 157 | */ 158 | function sqrt(uint256 a) internal pure returns (uint256) { 159 | if (a == 0) { 160 | return 0; 161 | } 162 | 163 | // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. 164 | // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have 165 | // `msb(a) <= a < 2*msb(a)`. 166 | // We also know that `k`, the position of the most significant bit, is such that `msb(a) = 2**k`. 167 | // This gives `2**k < a <= 2**(k+1)` → `2**(k/2) <= sqrt(a) < 2 ** (k/2+1)`. 168 | // Using an algorithm similar to the msb conmputation, we are able to compute `result = 2**(k/2)` which is a 169 | // good first aproximation of `sqrt(a)` with at least 1 correct bit. 170 | uint256 result = 1; 171 | uint256 x = a; 172 | if (x >> 128 > 0) { 173 | x >>= 128; 174 | result <<= 64; 175 | } 176 | if (x >> 64 > 0) { 177 | x >>= 64; 178 | result <<= 32; 179 | } 180 | if (x >> 32 > 0) { 181 | x >>= 32; 182 | result <<= 16; 183 | } 184 | if (x >> 16 > 0) { 185 | x >>= 16; 186 | result <<= 8; 187 | } 188 | if (x >> 8 > 0) { 189 | x >>= 8; 190 | result <<= 4; 191 | } 192 | if (x >> 4 > 0) { 193 | x >>= 4; 194 | result <<= 2; 195 | } 196 | if (x >> 2 > 0) { 197 | result <<= 1; 198 | } 199 | 200 | // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, 201 | // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at 202 | // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision 203 | // into the expected uint128 result. 204 | unchecked { 205 | result = (result + a / result) >> 1; 206 | result = (result + a / result) >> 1; 207 | result = (result + a / result) >> 1; 208 | result = (result + a / result) >> 1; 209 | result = (result + a / result) >> 1; 210 | result = (result + a / result) >> 1; 211 | result = (result + a / result) >> 1; 212 | return min(result, a / result); 213 | } 214 | } 215 | 216 | /** 217 | * @notice Calculates sqrt(a), following the selected rounding direction. 218 | */ 219 | function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { 220 | uint256 result = sqrt(a); 221 | if (rounding == Rounding.Up && result * result < a) { 222 | result += 1; 223 | } 224 | return result; 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/token/ERC20/extensions/ERC20Votes.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Votes.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "./draft-ERC20Permit.sol"; 7 | import "../../../utils/math/Math.sol"; 8 | import "../../../governance/utils/IVotes.sol"; 9 | import "../../../utils/math/SafeCast.sol"; 10 | import "../../../utils/cryptography/ECDSA.sol"; 11 | 12 | /** 13 | * @dev Extension of ERC20 to support Compound-like voting and delegation. This version is more generic than Compound's, 14 | * and supports token supply up to 2^224^ - 1, while COMP is limited to 2^96^ - 1. 15 | * 16 | * NOTE: If exact COMP compatibility is required, use the {ERC20VotesComp} variant of this module. 17 | * 18 | * This extension keeps a history (checkpoints) of each account's vote power. Vote power can be delegated either 19 | * by calling the {delegate} function directly, or by providing a signature to be used with {delegateBySig}. Voting 20 | * power can be queried through the public accessors {getVotes} and {getPastVotes}. 21 | * 22 | * By default, token balance does not account for voting power. This makes transfers cheaper. The downside is that it 23 | * requires users to delegate to themselves in order to activate checkpoints and have their voting power tracked. 24 | * 25 | * _Available since v4.2._ 26 | */ 27 | abstract contract ERC20Votes is IVotes, ERC20Permit { 28 | struct Checkpoint { 29 | uint32 fromBlock; 30 | uint224 votes; 31 | } 32 | 33 | bytes32 private constant _DELEGATION_TYPEHASH = 34 | keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); 35 | 36 | mapping(address => address) private _delegates; 37 | mapping(address => Checkpoint[]) private _checkpoints; 38 | Checkpoint[] private _totalSupplyCheckpoints; 39 | 40 | /** 41 | * @dev Get the `pos`-th checkpoint for `account`. 42 | */ 43 | function checkpoints(address account, uint32 pos) public view virtual returns (Checkpoint memory) { 44 | return _checkpoints[account][pos]; 45 | } 46 | 47 | /** 48 | * @dev Get number of checkpoints for `account`. 49 | */ 50 | function numCheckpoints(address account) public view virtual returns (uint32) { 51 | return SafeCast.toUint32(_checkpoints[account].length); 52 | } 53 | 54 | /** 55 | * @dev Get the address `account` is currently delegating to. 56 | */ 57 | function delegates(address account) public view virtual override returns (address) { 58 | return _delegates[account]; 59 | } 60 | 61 | /** 62 | * @dev Gets the current votes balance for `account` 63 | */ 64 | function getVotes(address account) public view virtual override returns (uint256) { 65 | uint256 pos = _checkpoints[account].length; 66 | return pos == 0 ? 0 : _checkpoints[account][pos - 1].votes; 67 | } 68 | 69 | /** 70 | * @dev Retrieve the number of votes for `account` at the end of `blockNumber`. 71 | * 72 | * Requirements: 73 | * 74 | * - `blockNumber` must have been already mined 75 | */ 76 | function getPastVotes(address account, uint256 blockNumber) public view virtual override returns (uint256) { 77 | require(blockNumber < block.number, "ERC20Votes: block not yet mined"); 78 | return _checkpointsLookup(_checkpoints[account], blockNumber); 79 | } 80 | 81 | /** 82 | * @dev Retrieve the `totalSupply` at the end of `blockNumber`. Note, this value is the sum of all balances. 83 | * It is but NOT the sum of all the delegated votes! 84 | * 85 | * Requirements: 86 | * 87 | * - `blockNumber` must have been already mined 88 | */ 89 | function getPastTotalSupply(uint256 blockNumber) public view virtual override returns (uint256) { 90 | require(blockNumber < block.number, "ERC20Votes: block not yet mined"); 91 | return _checkpointsLookup(_totalSupplyCheckpoints, blockNumber); 92 | } 93 | 94 | /** 95 | * @dev Lookup a value in a list of (sorted) checkpoints. 96 | */ 97 | function _checkpointsLookup(Checkpoint[] storage ckpts, uint256 blockNumber) private view returns (uint256) { 98 | // We run a binary search to look for the earliest checkpoint taken after `blockNumber`. 99 | // 100 | // During the loop, the index of the wanted checkpoint remains in the range [low-1, high). 101 | // With each iteration, either `low` or `high` is moved towards the middle of the range to maintain the invariant. 102 | // - If the middle checkpoint is after `blockNumber`, we look in [low, mid) 103 | // - If the middle checkpoint is before or equal to `blockNumber`, we look in [mid+1, high) 104 | // Once we reach a single value (when low == high), we've found the right checkpoint at the index high-1, if not 105 | // out of bounds (in which case we're looking too far in the past and the result is 0). 106 | // Note that if the latest checkpoint available is exactly for `blockNumber`, we end up with an index that is 107 | // past the end of the array, so we technically don't find a checkpoint after `blockNumber`, but it works out 108 | // the same. 109 | uint256 high = ckpts.length; 110 | uint256 low = 0; 111 | while (low < high) { 112 | uint256 mid = Math.average(low, high); 113 | if (ckpts[mid].fromBlock > blockNumber) { 114 | high = mid; 115 | } else { 116 | low = mid + 1; 117 | } 118 | } 119 | 120 | return high == 0 ? 0 : ckpts[high - 1].votes; 121 | } 122 | 123 | /** 124 | * @dev Delegate votes from the sender to `delegatee`. 125 | */ 126 | function delegate(address delegatee) public virtual override { 127 | _delegate(_msgSender(), delegatee); 128 | } 129 | 130 | /** 131 | * @dev Delegates votes from signer to `delegatee` 132 | */ 133 | function delegateBySig( 134 | address delegatee, 135 | uint256 nonce, 136 | uint256 expiry, 137 | uint8 v, 138 | bytes32 r, 139 | bytes32 s 140 | ) public virtual override { 141 | require(block.timestamp <= expiry, "ERC20Votes: signature expired"); 142 | address signer = ECDSA.recover( 143 | _hashTypedDataV4(keccak256(abi.encode(_DELEGATION_TYPEHASH, delegatee, nonce, expiry))), 144 | v, 145 | r, 146 | s 147 | ); 148 | require(nonce == _useNonce(signer), "ERC20Votes: invalid nonce"); 149 | _delegate(signer, delegatee); 150 | } 151 | 152 | /** 153 | * @dev Maximum token supply. Defaults to `type(uint224).max` (2^224^ - 1). 154 | */ 155 | function _maxSupply() internal view virtual returns (uint224) { 156 | return type(uint224).max; 157 | } 158 | 159 | /** 160 | * @dev Snapshots the totalSupply after it has been increased. 161 | */ 162 | function _mint(address account, uint256 amount) internal virtual override { 163 | super._mint(account, amount); 164 | require(totalSupply() <= _maxSupply(), "ERC20Votes: total supply risks overflowing votes"); 165 | 166 | _writeCheckpoint(_totalSupplyCheckpoints, _add, amount); 167 | } 168 | 169 | /** 170 | * @dev Snapshots the totalSupply after it has been decreased. 171 | */ 172 | function _burn(address account, uint256 amount) internal virtual override { 173 | super._burn(account, amount); 174 | 175 | _writeCheckpoint(_totalSupplyCheckpoints, _subtract, amount); 176 | } 177 | 178 | /** 179 | * @dev Move voting power when tokens are transferred. 180 | * 181 | * Emits a {DelegateVotesChanged} event. 182 | */ 183 | function _afterTokenTransfer( 184 | address from, 185 | address to, 186 | uint256 amount 187 | ) internal virtual override { 188 | super._afterTokenTransfer(from, to, amount); 189 | 190 | _moveVotingPower(delegates(from), delegates(to), amount); 191 | } 192 | 193 | /** 194 | * @dev Change delegation for `delegator` to `delegatee`. 195 | * 196 | * Emits events {DelegateChanged} and {DelegateVotesChanged}. 197 | */ 198 | function _delegate(address delegator, address delegatee) internal virtual { 199 | address currentDelegate = delegates(delegator); 200 | uint256 delegatorBalance = balanceOf(delegator); 201 | _delegates[delegator] = delegatee; 202 | 203 | emit DelegateChanged(delegator, currentDelegate, delegatee); 204 | 205 | _moveVotingPower(currentDelegate, delegatee, delegatorBalance); 206 | } 207 | 208 | function _moveVotingPower( 209 | address src, 210 | address dst, 211 | uint256 amount 212 | ) private { 213 | if (src != dst && amount > 0) { 214 | if (src != address(0)) { 215 | (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[src], _subtract, amount); 216 | emit DelegateVotesChanged(src, oldWeight, newWeight); 217 | } 218 | 219 | if (dst != address(0)) { 220 | (uint256 oldWeight, uint256 newWeight) = _writeCheckpoint(_checkpoints[dst], _add, amount); 221 | emit DelegateVotesChanged(dst, oldWeight, newWeight); 222 | } 223 | } 224 | } 225 | 226 | function _writeCheckpoint( 227 | Checkpoint[] storage ckpts, 228 | function(uint256, uint256) view returns (uint256) op, 229 | uint256 delta 230 | ) private returns (uint256 oldWeight, uint256 newWeight) { 231 | uint256 pos = ckpts.length; 232 | oldWeight = pos == 0 ? 0 : ckpts[pos - 1].votes; 233 | newWeight = op(oldWeight, delta); 234 | 235 | if (pos > 0 && ckpts[pos - 1].fromBlock == block.number) { 236 | ckpts[pos - 1].votes = SafeCast.toUint224(newWeight); 237 | } else { 238 | ckpts.push(Checkpoint({fromBlock: SafeCast.toUint32(block.number), votes: SafeCast.toUint224(newWeight)})); 239 | } 240 | } 241 | 242 | function _add(uint256 a, uint256 b) private pure returns (uint256) { 243 | return a + b; 244 | } 245 | 246 | function _subtract(uint256 a, uint256 b) private pure returns (uint256) { 247 | return a - b; 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/token/ERC20/ERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.7.0) (token/ERC20/ERC20.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | import "./IERC20.sol"; 7 | import "./extensions/IERC20Metadata.sol"; 8 | import "../../utils/Context.sol"; 9 | 10 | /** 11 | * @dev Implementation of the {IERC20} interface. 12 | * 13 | * This implementation is agnostic to the way tokens are created. This means 14 | * that a supply mechanism has to be added in a derived contract using {_mint}. 15 | * For a generic mechanism see {ERC20PresetMinterPauser}. 16 | * 17 | * TIP: For a detailed writeup see our guide 18 | * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 19 | * to implement supply mechanisms]. 20 | * 21 | * We have followed general OpenZeppelin Contracts guidelines: functions revert 22 | * instead returning `false` on failure. This behavior is nonetheless 23 | * conventional and does not conflict with the expectations of ERC20 24 | * applications. 25 | * 26 | * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 27 | * This allows applications to reconstruct the allowance for all accounts just 28 | * by listening to said events. Other implementations of the EIP may not emit 29 | * these events, as it isn't required by the specification. 30 | * 31 | * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 32 | * functions have been added to mitigate the well-known issues around setting 33 | * allowances. See {IERC20-approve}. 34 | */ 35 | contract ERC20 is Context, IERC20, IERC20Metadata { 36 | mapping(address => uint256) private _balances; 37 | 38 | mapping(address => mapping(address => uint256)) private _allowances; 39 | 40 | uint256 private _totalSupply; 41 | 42 | string private _name; 43 | string private _symbol; 44 | 45 | /** 46 | * @dev Sets the values for {name} and {symbol}. 47 | * 48 | * The default value of {decimals} is 18. To select a different value for 49 | * {decimals} you should overload it. 50 | * 51 | * All two of these values are immutable: they can only be set once during 52 | * construction. 53 | */ 54 | constructor(string memory name_, string memory symbol_) { 55 | _name = name_; 56 | _symbol = symbol_; 57 | } 58 | 59 | /** 60 | * @dev Returns the name of the token. 61 | */ 62 | function name() public view virtual override returns (string memory) { 63 | return _name; 64 | } 65 | 66 | /** 67 | * @dev Returns the symbol of the token, usually a shorter version of the 68 | * name. 69 | */ 70 | function symbol() public view virtual override returns (string memory) { 71 | return _symbol; 72 | } 73 | 74 | /** 75 | * @dev Returns the number of decimals used to get its user representation. 76 | * For example, if `decimals` equals `2`, a balance of `505` tokens should 77 | * be displayed to a user as `5.05` (`505 / 10 ** 2`). 78 | * 79 | * Tokens usually opt for a value of 18, imitating the relationship between 80 | * Ether and Wei. This is the value {ERC20} uses, unless this function is 81 | * overridden; 82 | * 83 | * NOTE: This information is only used for _display_ purposes: it in 84 | * no way affects any of the arithmetic of the contract, including 85 | * {IERC20-balanceOf} and {IERC20-transfer}. 86 | */ 87 | function decimals() public view virtual override returns (uint8) { 88 | return 18; 89 | } 90 | 91 | /** 92 | * @dev See {IERC20-totalSupply}. 93 | */ 94 | function totalSupply() public view virtual override returns (uint256) { 95 | return _totalSupply; 96 | } 97 | 98 | /** 99 | * @dev See {IERC20-balanceOf}. 100 | */ 101 | function balanceOf(address account) public view virtual override returns (uint256) { 102 | return _balances[account]; 103 | } 104 | 105 | /** 106 | * @dev See {IERC20-transfer}. 107 | * 108 | * Requirements: 109 | * 110 | * - `to` cannot be the zero address. 111 | * - the caller must have a balance of at least `amount`. 112 | */ 113 | function transfer(address to, uint256 amount) public virtual override returns (bool) { 114 | address owner = _msgSender(); 115 | _transfer(owner, to, amount); 116 | return true; 117 | } 118 | 119 | /** 120 | * @dev See {IERC20-allowance}. 121 | */ 122 | function allowance(address owner, address spender) public view virtual override returns (uint256) { 123 | return _allowances[owner][spender]; 124 | } 125 | 126 | /** 127 | * @dev See {IERC20-approve}. 128 | * 129 | * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on 130 | * `transferFrom`. This is semantically equivalent to an infinite approval. 131 | * 132 | * Requirements: 133 | * 134 | * - `spender` cannot be the zero address. 135 | */ 136 | function approve(address spender, uint256 amount) public virtual override returns (bool) { 137 | address owner = _msgSender(); 138 | _approve(owner, spender, amount); 139 | return true; 140 | } 141 | 142 | /** 143 | * @dev See {IERC20-transferFrom}. 144 | * 145 | * Emits an {Approval} event indicating the updated allowance. This is not 146 | * required by the EIP. See the note at the beginning of {ERC20}. 147 | * 148 | * NOTE: Does not update the allowance if the current allowance 149 | * is the maximum `uint256`. 150 | * 151 | * Requirements: 152 | * 153 | * - `from` and `to` cannot be the zero address. 154 | * - `from` must have a balance of at least `amount`. 155 | * - the caller must have allowance for ``from``'s tokens of at least 156 | * `amount`. 157 | */ 158 | function transferFrom( 159 | address from, 160 | address to, 161 | uint256 amount 162 | ) public virtual override returns (bool) { 163 | address spender = _msgSender(); 164 | _spendAllowance(from, spender, amount); 165 | _transfer(from, to, amount); 166 | return true; 167 | } 168 | 169 | /** 170 | * @dev Atomically increases the allowance granted to `spender` by the caller. 171 | * 172 | * This is an alternative to {approve} that can be used as a mitigation for 173 | * problems described in {IERC20-approve}. 174 | * 175 | * Emits an {Approval} event indicating the updated allowance. 176 | * 177 | * Requirements: 178 | * 179 | * - `spender` cannot be the zero address. 180 | */ 181 | function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 182 | address owner = _msgSender(); 183 | _approve(owner, spender, allowance(owner, spender) + addedValue); 184 | return true; 185 | } 186 | 187 | /** 188 | * @dev Atomically decreases the allowance granted to `spender` by the caller. 189 | * 190 | * This is an alternative to {approve} that can be used as a mitigation for 191 | * problems described in {IERC20-approve}. 192 | * 193 | * Emits an {Approval} event indicating the updated allowance. 194 | * 195 | * Requirements: 196 | * 197 | * - `spender` cannot be the zero address. 198 | * - `spender` must have allowance for the caller of at least 199 | * `subtractedValue`. 200 | */ 201 | function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 202 | address owner = _msgSender(); 203 | uint256 currentAllowance = allowance(owner, spender); 204 | require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero"); 205 | unchecked { 206 | _approve(owner, spender, currentAllowance - subtractedValue); 207 | } 208 | 209 | return true; 210 | } 211 | 212 | /** 213 | * @dev Moves `amount` of tokens from `from` to `to`. 214 | * 215 | * This internal function is equivalent to {transfer}, and can be used to 216 | * e.g. implement automatic token fees, slashing mechanisms, etc. 217 | * 218 | * Emits a {Transfer} event. 219 | * 220 | * Requirements: 221 | * 222 | * - `from` cannot be the zero address. 223 | * - `to` cannot be the zero address. 224 | * - `from` must have a balance of at least `amount`. 225 | */ 226 | function _transfer( 227 | address from, 228 | address to, 229 | uint256 amount 230 | ) internal virtual { 231 | require(from != address(0), "ERC20: transfer from the zero address"); 232 | require(to != address(0), "ERC20: transfer to the zero address"); 233 | 234 | _beforeTokenTransfer(from, to, amount); 235 | 236 | uint256 fromBalance = _balances[from]; 237 | require(fromBalance >= amount, "ERC20: transfer amount exceeds balance"); 238 | unchecked { 239 | _balances[from] = fromBalance - amount; 240 | } 241 | _balances[to] += amount; 242 | 243 | emit Transfer(from, to, amount); 244 | 245 | _afterTokenTransfer(from, to, amount); 246 | } 247 | 248 | /** @dev Creates `amount` tokens and assigns them to `account`, increasing 249 | * the total supply. 250 | * 251 | * Emits a {Transfer} event with `from` set to the zero address. 252 | * 253 | * Requirements: 254 | * 255 | * - `account` cannot be the zero address. 256 | */ 257 | function _mint(address account, uint256 amount) internal virtual { 258 | require(account != address(0), "ERC20: mint to the zero address"); 259 | 260 | _beforeTokenTransfer(address(0), account, amount); 261 | 262 | _totalSupply += amount; 263 | _balances[account] += amount; 264 | emit Transfer(address(0), account, amount); 265 | 266 | _afterTokenTransfer(address(0), account, amount); 267 | } 268 | 269 | /** 270 | * @dev Destroys `amount` tokens from `account`, reducing the 271 | * total supply. 272 | * 273 | * Emits a {Transfer} event with `to` set to the zero address. 274 | * 275 | * Requirements: 276 | * 277 | * - `account` cannot be the zero address. 278 | * - `account` must have at least `amount` tokens. 279 | */ 280 | function _burn(address account, uint256 amount) internal virtual { 281 | require(account != address(0), "ERC20: burn from the zero address"); 282 | 283 | _beforeTokenTransfer(account, address(0), amount); 284 | 285 | uint256 accountBalance = _balances[account]; 286 | require(accountBalance >= amount, "ERC20: burn amount exceeds balance"); 287 | unchecked { 288 | _balances[account] = accountBalance - amount; 289 | } 290 | _totalSupply -= amount; 291 | 292 | emit Transfer(account, address(0), amount); 293 | 294 | _afterTokenTransfer(account, address(0), amount); 295 | } 296 | 297 | /** 298 | * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 299 | * 300 | * This internal function is equivalent to `approve`, and can be used to 301 | * e.g. set automatic allowances for certain subsystems, etc. 302 | * 303 | * Emits an {Approval} event. 304 | * 305 | * Requirements: 306 | * 307 | * - `owner` cannot be the zero address. 308 | * - `spender` cannot be the zero address. 309 | */ 310 | function _approve( 311 | address owner, 312 | address spender, 313 | uint256 amount 314 | ) internal virtual { 315 | require(owner != address(0), "ERC20: approve from the zero address"); 316 | require(spender != address(0), "ERC20: approve to the zero address"); 317 | 318 | _allowances[owner][spender] = amount; 319 | emit Approval(owner, spender, amount); 320 | } 321 | 322 | /** 323 | * @dev Updates `owner` s allowance for `spender` based on spent `amount`. 324 | * 325 | * Does not update the allowance amount in case of infinite allowance. 326 | * Revert if not enough allowance is available. 327 | * 328 | * Might emit an {Approval} event. 329 | */ 330 | function _spendAllowance( 331 | address owner, 332 | address spender, 333 | uint256 amount 334 | ) internal virtual { 335 | uint256 currentAllowance = allowance(owner, spender); 336 | if (currentAllowance != type(uint256).max) { 337 | require(currentAllowance >= amount, "ERC20: insufficient allowance"); 338 | unchecked { 339 | _approve(owner, spender, currentAllowance - amount); 340 | } 341 | } 342 | } 343 | 344 | /** 345 | * @dev Hook that is called before any transfer of tokens. This includes 346 | * minting and burning. 347 | * 348 | * Calling conditions: 349 | * 350 | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 351 | * will be transferred to `to`. 352 | * - when `from` is zero, `amount` tokens will be minted for `to`. 353 | * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 354 | * - `from` and `to` are never both zero. 355 | * 356 | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 357 | */ 358 | function _beforeTokenTransfer( 359 | address from, 360 | address to, 361 | uint256 amount 362 | ) internal virtual {} 363 | 364 | /** 365 | * @dev Hook that is called after any transfer of tokens. This includes 366 | * minting and burning. 367 | * 368 | * Calling conditions: 369 | * 370 | * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 371 | * has been transferred to `to`. 372 | * - when `from` is zero, `amount` tokens have been minted for `to`. 373 | * - when `to` is zero, `amount` of ``from``'s tokens have been burned. 374 | * - `from` and `to` are never both zero. 375 | * 376 | * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 377 | */ 378 | function _afterTokenTransfer( 379 | address from, 380 | address to, 381 | uint256 amount 382 | ) internal virtual {} 383 | } 384 | -------------------------------------------------------------------------------- /src/starkware/isd/third_party/open_zeppelin/utils/math/SafeCast.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | // OpenZeppelin Contracts (last updated v4.7.0) (utils/math/SafeCast.sol) 3 | 4 | pragma solidity ^0.8.0; 5 | 6 | /** 7 | * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow 8 | * checks. 9 | * 10 | * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can 11 | * easily result in undesired exploitation or bugs, since developers usually 12 | * assume that overflows raise errors. `SafeCast` restores this intuition by 13 | * reverting the transaction when such an operation overflows. 14 | * 15 | * Using this library instead of the unchecked operations eliminates an entire 16 | * class of bugs, so it's recommended to use it always. 17 | * 18 | * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing 19 | * all math on `uint256` and `int256` and then downcasting. 20 | */ 21 | library SafeCast { 22 | /** 23 | * @dev Returns the downcasted uint248 from uint256, reverting on 24 | * overflow (when the input is greater than largest uint248). 25 | * 26 | * Counterpart to Solidity's `uint248` operator. 27 | * 28 | * Requirements: 29 | * 30 | * - input must fit into 248 bits 31 | * 32 | * _Available since v4.7._ 33 | */ 34 | function toUint248(uint256 value) internal pure returns (uint248) { 35 | require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits"); 36 | return uint248(value); 37 | } 38 | 39 | /** 40 | * @dev Returns the downcasted uint240 from uint256, reverting on 41 | * overflow (when the input is greater than largest uint240). 42 | * 43 | * Counterpart to Solidity's `uint240` operator. 44 | * 45 | * Requirements: 46 | * 47 | * - input must fit into 240 bits 48 | * 49 | * _Available since v4.7._ 50 | */ 51 | function toUint240(uint256 value) internal pure returns (uint240) { 52 | require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits"); 53 | return uint240(value); 54 | } 55 | 56 | /** 57 | * @dev Returns the downcasted uint232 from uint256, reverting on 58 | * overflow (when the input is greater than largest uint232). 59 | * 60 | * Counterpart to Solidity's `uint232` operator. 61 | * 62 | * Requirements: 63 | * 64 | * - input must fit into 232 bits 65 | * 66 | * _Available since v4.7._ 67 | */ 68 | function toUint232(uint256 value) internal pure returns (uint232) { 69 | require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits"); 70 | return uint232(value); 71 | } 72 | 73 | /** 74 | * @dev Returns the downcasted uint224 from uint256, reverting on 75 | * overflow (when the input is greater than largest uint224). 76 | * 77 | * Counterpart to Solidity's `uint224` operator. 78 | * 79 | * Requirements: 80 | * 81 | * - input must fit into 224 bits 82 | * 83 | * _Available since v4.2._ 84 | */ 85 | function toUint224(uint256 value) internal pure returns (uint224) { 86 | require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits"); 87 | return uint224(value); 88 | } 89 | 90 | /** 91 | * @dev Returns the downcasted uint216 from uint256, reverting on 92 | * overflow (when the input is greater than largest uint216). 93 | * 94 | * Counterpart to Solidity's `uint216` operator. 95 | * 96 | * Requirements: 97 | * 98 | * - input must fit into 216 bits 99 | * 100 | * _Available since v4.7._ 101 | */ 102 | function toUint216(uint256 value) internal pure returns (uint216) { 103 | require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits"); 104 | return uint216(value); 105 | } 106 | 107 | /** 108 | * @dev Returns the downcasted uint208 from uint256, reverting on 109 | * overflow (when the input is greater than largest uint208). 110 | * 111 | * Counterpart to Solidity's `uint208` operator. 112 | * 113 | * Requirements: 114 | * 115 | * - input must fit into 208 bits 116 | * 117 | * _Available since v4.7._ 118 | */ 119 | function toUint208(uint256 value) internal pure returns (uint208) { 120 | require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits"); 121 | return uint208(value); 122 | } 123 | 124 | /** 125 | * @dev Returns the downcasted uint200 from uint256, reverting on 126 | * overflow (when the input is greater than largest uint200). 127 | * 128 | * Counterpart to Solidity's `uint200` operator. 129 | * 130 | * Requirements: 131 | * 132 | * - input must fit into 200 bits 133 | * 134 | * _Available since v4.7._ 135 | */ 136 | function toUint200(uint256 value) internal pure returns (uint200) { 137 | require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits"); 138 | return uint200(value); 139 | } 140 | 141 | /** 142 | * @dev Returns the downcasted uint192 from uint256, reverting on 143 | * overflow (when the input is greater than largest uint192). 144 | * 145 | * Counterpart to Solidity's `uint192` operator. 146 | * 147 | * Requirements: 148 | * 149 | * - input must fit into 192 bits 150 | * 151 | * _Available since v4.7._ 152 | */ 153 | function toUint192(uint256 value) internal pure returns (uint192) { 154 | require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits"); 155 | return uint192(value); 156 | } 157 | 158 | /** 159 | * @dev Returns the downcasted uint184 from uint256, reverting on 160 | * overflow (when the input is greater than largest uint184). 161 | * 162 | * Counterpart to Solidity's `uint184` operator. 163 | * 164 | * Requirements: 165 | * 166 | * - input must fit into 184 bits 167 | * 168 | * _Available since v4.7._ 169 | */ 170 | function toUint184(uint256 value) internal pure returns (uint184) { 171 | require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits"); 172 | return uint184(value); 173 | } 174 | 175 | /** 176 | * @dev Returns the downcasted uint176 from uint256, reverting on 177 | * overflow (when the input is greater than largest uint176). 178 | * 179 | * Counterpart to Solidity's `uint176` operator. 180 | * 181 | * Requirements: 182 | * 183 | * - input must fit into 176 bits 184 | * 185 | * _Available since v4.7._ 186 | */ 187 | function toUint176(uint256 value) internal pure returns (uint176) { 188 | require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits"); 189 | return uint176(value); 190 | } 191 | 192 | /** 193 | * @dev Returns the downcasted uint168 from uint256, reverting on 194 | * overflow (when the input is greater than largest uint168). 195 | * 196 | * Counterpart to Solidity's `uint168` operator. 197 | * 198 | * Requirements: 199 | * 200 | * - input must fit into 168 bits 201 | * 202 | * _Available since v4.7._ 203 | */ 204 | function toUint168(uint256 value) internal pure returns (uint168) { 205 | require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits"); 206 | return uint168(value); 207 | } 208 | 209 | /** 210 | * @dev Returns the downcasted uint160 from uint256, reverting on 211 | * overflow (when the input is greater than largest uint160). 212 | * 213 | * Counterpart to Solidity's `uint160` operator. 214 | * 215 | * Requirements: 216 | * 217 | * - input must fit into 160 bits 218 | * 219 | * _Available since v4.7._ 220 | */ 221 | function toUint160(uint256 value) internal pure returns (uint160) { 222 | require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits"); 223 | return uint160(value); 224 | } 225 | 226 | /** 227 | * @dev Returns the downcasted uint152 from uint256, reverting on 228 | * overflow (when the input is greater than largest uint152). 229 | * 230 | * Counterpart to Solidity's `uint152` operator. 231 | * 232 | * Requirements: 233 | * 234 | * - input must fit into 152 bits 235 | * 236 | * _Available since v4.7._ 237 | */ 238 | function toUint152(uint256 value) internal pure returns (uint152) { 239 | require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits"); 240 | return uint152(value); 241 | } 242 | 243 | /** 244 | * @dev Returns the downcasted uint144 from uint256, reverting on 245 | * overflow (when the input is greater than largest uint144). 246 | * 247 | * Counterpart to Solidity's `uint144` operator. 248 | * 249 | * Requirements: 250 | * 251 | * - input must fit into 144 bits 252 | * 253 | * _Available since v4.7._ 254 | */ 255 | function toUint144(uint256 value) internal pure returns (uint144) { 256 | require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits"); 257 | return uint144(value); 258 | } 259 | 260 | /** 261 | * @dev Returns the downcasted uint136 from uint256, reverting on 262 | * overflow (when the input is greater than largest uint136). 263 | * 264 | * Counterpart to Solidity's `uint136` operator. 265 | * 266 | * Requirements: 267 | * 268 | * - input must fit into 136 bits 269 | * 270 | * _Available since v4.7._ 271 | */ 272 | function toUint136(uint256 value) internal pure returns (uint136) { 273 | require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits"); 274 | return uint136(value); 275 | } 276 | 277 | /** 278 | * @dev Returns the downcasted uint128 from uint256, reverting on 279 | * overflow (when the input is greater than largest uint128). 280 | * 281 | * Counterpart to Solidity's `uint128` operator. 282 | * 283 | * Requirements: 284 | * 285 | * - input must fit into 128 bits 286 | * 287 | * _Available since v2.5._ 288 | */ 289 | function toUint128(uint256 value) internal pure returns (uint128) { 290 | require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits"); 291 | return uint128(value); 292 | } 293 | 294 | /** 295 | * @dev Returns the downcasted uint120 from uint256, reverting on 296 | * overflow (when the input is greater than largest uint120). 297 | * 298 | * Counterpart to Solidity's `uint120` operator. 299 | * 300 | * Requirements: 301 | * 302 | * - input must fit into 120 bits 303 | * 304 | * _Available since v4.7._ 305 | */ 306 | function toUint120(uint256 value) internal pure returns (uint120) { 307 | require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits"); 308 | return uint120(value); 309 | } 310 | 311 | /** 312 | * @dev Returns the downcasted uint112 from uint256, reverting on 313 | * overflow (when the input is greater than largest uint112). 314 | * 315 | * Counterpart to Solidity's `uint112` operator. 316 | * 317 | * Requirements: 318 | * 319 | * - input must fit into 112 bits 320 | * 321 | * _Available since v4.7._ 322 | */ 323 | function toUint112(uint256 value) internal pure returns (uint112) { 324 | require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits"); 325 | return uint112(value); 326 | } 327 | 328 | /** 329 | * @dev Returns the downcasted uint104 from uint256, reverting on 330 | * overflow (when the input is greater than largest uint104). 331 | * 332 | * Counterpart to Solidity's `uint104` operator. 333 | * 334 | * Requirements: 335 | * 336 | * - input must fit into 104 bits 337 | * 338 | * _Available since v4.7._ 339 | */ 340 | function toUint104(uint256 value) internal pure returns (uint104) { 341 | require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits"); 342 | return uint104(value); 343 | } 344 | 345 | /** 346 | * @dev Returns the downcasted uint96 from uint256, reverting on 347 | * overflow (when the input is greater than largest uint96). 348 | * 349 | * Counterpart to Solidity's `uint96` operator. 350 | * 351 | * Requirements: 352 | * 353 | * - input must fit into 96 bits 354 | * 355 | * _Available since v4.2._ 356 | */ 357 | function toUint96(uint256 value) internal pure returns (uint96) { 358 | require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits"); 359 | return uint96(value); 360 | } 361 | 362 | /** 363 | * @dev Returns the downcasted uint88 from uint256, reverting on 364 | * overflow (when the input is greater than largest uint88). 365 | * 366 | * Counterpart to Solidity's `uint88` operator. 367 | * 368 | * Requirements: 369 | * 370 | * - input must fit into 88 bits 371 | * 372 | * _Available since v4.7._ 373 | */ 374 | function toUint88(uint256 value) internal pure returns (uint88) { 375 | require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits"); 376 | return uint88(value); 377 | } 378 | 379 | /** 380 | * @dev Returns the downcasted uint80 from uint256, reverting on 381 | * overflow (when the input is greater than largest uint80). 382 | * 383 | * Counterpart to Solidity's `uint80` operator. 384 | * 385 | * Requirements: 386 | * 387 | * - input must fit into 80 bits 388 | * 389 | * _Available since v4.7._ 390 | */ 391 | function toUint80(uint256 value) internal pure returns (uint80) { 392 | require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits"); 393 | return uint80(value); 394 | } 395 | 396 | /** 397 | * @dev Returns the downcasted uint72 from uint256, reverting on 398 | * overflow (when the input is greater than largest uint72). 399 | * 400 | * Counterpart to Solidity's `uint72` operator. 401 | * 402 | * Requirements: 403 | * 404 | * - input must fit into 72 bits 405 | * 406 | * _Available since v4.7._ 407 | */ 408 | function toUint72(uint256 value) internal pure returns (uint72) { 409 | require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits"); 410 | return uint72(value); 411 | } 412 | 413 | /** 414 | * @dev Returns the downcasted uint64 from uint256, reverting on 415 | * overflow (when the input is greater than largest uint64). 416 | * 417 | * Counterpart to Solidity's `uint64` operator. 418 | * 419 | * Requirements: 420 | * 421 | * - input must fit into 64 bits 422 | * 423 | * _Available since v2.5._ 424 | */ 425 | function toUint64(uint256 value) internal pure returns (uint64) { 426 | require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits"); 427 | return uint64(value); 428 | } 429 | 430 | /** 431 | * @dev Returns the downcasted uint56 from uint256, reverting on 432 | * overflow (when the input is greater than largest uint56). 433 | * 434 | * Counterpart to Solidity's `uint56` operator. 435 | * 436 | * Requirements: 437 | * 438 | * - input must fit into 56 bits 439 | * 440 | * _Available since v4.7._ 441 | */ 442 | function toUint56(uint256 value) internal pure returns (uint56) { 443 | require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits"); 444 | return uint56(value); 445 | } 446 | 447 | /** 448 | * @dev Returns the downcasted uint48 from uint256, reverting on 449 | * overflow (when the input is greater than largest uint48). 450 | * 451 | * Counterpart to Solidity's `uint48` operator. 452 | * 453 | * Requirements: 454 | * 455 | * - input must fit into 48 bits 456 | * 457 | * _Available since v4.7._ 458 | */ 459 | function toUint48(uint256 value) internal pure returns (uint48) { 460 | require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits"); 461 | return uint48(value); 462 | } 463 | 464 | /** 465 | * @dev Returns the downcasted uint40 from uint256, reverting on 466 | * overflow (when the input is greater than largest uint40). 467 | * 468 | * Counterpart to Solidity's `uint40` operator. 469 | * 470 | * Requirements: 471 | * 472 | * - input must fit into 40 bits 473 | * 474 | * _Available since v4.7._ 475 | */ 476 | function toUint40(uint256 value) internal pure returns (uint40) { 477 | require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits"); 478 | return uint40(value); 479 | } 480 | 481 | /** 482 | * @dev Returns the downcasted uint32 from uint256, reverting on 483 | * overflow (when the input is greater than largest uint32). 484 | * 485 | * Counterpart to Solidity's `uint32` operator. 486 | * 487 | * Requirements: 488 | * 489 | * - input must fit into 32 bits 490 | * 491 | * _Available since v2.5._ 492 | */ 493 | function toUint32(uint256 value) internal pure returns (uint32) { 494 | require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits"); 495 | return uint32(value); 496 | } 497 | 498 | /** 499 | * @dev Returns the downcasted uint24 from uint256, reverting on 500 | * overflow (when the input is greater than largest uint24). 501 | * 502 | * Counterpart to Solidity's `uint24` operator. 503 | * 504 | * Requirements: 505 | * 506 | * - input must fit into 24 bits 507 | * 508 | * _Available since v4.7._ 509 | */ 510 | function toUint24(uint256 value) internal pure returns (uint24) { 511 | require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits"); 512 | return uint24(value); 513 | } 514 | 515 | /** 516 | * @dev Returns the downcasted uint16 from uint256, reverting on 517 | * overflow (when the input is greater than largest uint16). 518 | * 519 | * Counterpart to Solidity's `uint16` operator. 520 | * 521 | * Requirements: 522 | * 523 | * - input must fit into 16 bits 524 | * 525 | * _Available since v2.5._ 526 | */ 527 | function toUint16(uint256 value) internal pure returns (uint16) { 528 | require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits"); 529 | return uint16(value); 530 | } 531 | 532 | /** 533 | * @dev Returns the downcasted uint8 from uint256, reverting on 534 | * overflow (when the input is greater than largest uint8). 535 | * 536 | * Counterpart to Solidity's `uint8` operator. 537 | * 538 | * Requirements: 539 | * 540 | * - input must fit into 8 bits 541 | * 542 | * _Available since v2.5._ 543 | */ 544 | function toUint8(uint256 value) internal pure returns (uint8) { 545 | require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits"); 546 | return uint8(value); 547 | } 548 | 549 | /** 550 | * @dev Converts a signed int256 into an unsigned uint256. 551 | * 552 | * Requirements: 553 | * 554 | * - input must be greater than or equal to 0. 555 | * 556 | * _Available since v3.0._ 557 | */ 558 | function toUint256(int256 value) internal pure returns (uint256) { 559 | require(value >= 0, "SafeCast: value must be positive"); 560 | return uint256(value); 561 | } 562 | 563 | /** 564 | * @dev Returns the downcasted int248 from int256, reverting on 565 | * overflow (when the input is less than smallest int248 or 566 | * greater than largest int248). 567 | * 568 | * Counterpart to Solidity's `int248` operator. 569 | * 570 | * Requirements: 571 | * 572 | * - input must fit into 248 bits 573 | * 574 | * _Available since v4.7._ 575 | */ 576 | function toInt248(int256 value) internal pure returns (int248) { 577 | require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits"); 578 | return int248(value); 579 | } 580 | 581 | /** 582 | * @dev Returns the downcasted int240 from int256, reverting on 583 | * overflow (when the input is less than smallest int240 or 584 | * greater than largest int240). 585 | * 586 | * Counterpart to Solidity's `int240` operator. 587 | * 588 | * Requirements: 589 | * 590 | * - input must fit into 240 bits 591 | * 592 | * _Available since v4.7._ 593 | */ 594 | function toInt240(int256 value) internal pure returns (int240) { 595 | require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits"); 596 | return int240(value); 597 | } 598 | 599 | /** 600 | * @dev Returns the downcasted int232 from int256, reverting on 601 | * overflow (when the input is less than smallest int232 or 602 | * greater than largest int232). 603 | * 604 | * Counterpart to Solidity's `int232` operator. 605 | * 606 | * Requirements: 607 | * 608 | * - input must fit into 232 bits 609 | * 610 | * _Available since v4.7._ 611 | */ 612 | function toInt232(int256 value) internal pure returns (int232) { 613 | require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits"); 614 | return int232(value); 615 | } 616 | 617 | /** 618 | * @dev Returns the downcasted int224 from int256, reverting on 619 | * overflow (when the input is less than smallest int224 or 620 | * greater than largest int224). 621 | * 622 | * Counterpart to Solidity's `int224` operator. 623 | * 624 | * Requirements: 625 | * 626 | * - input must fit into 224 bits 627 | * 628 | * _Available since v4.7._ 629 | */ 630 | function toInt224(int256 value) internal pure returns (int224) { 631 | require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits"); 632 | return int224(value); 633 | } 634 | 635 | /** 636 | * @dev Returns the downcasted int216 from int256, reverting on 637 | * overflow (when the input is less than smallest int216 or 638 | * greater than largest int216). 639 | * 640 | * Counterpart to Solidity's `int216` operator. 641 | * 642 | * Requirements: 643 | * 644 | * - input must fit into 216 bits 645 | * 646 | * _Available since v4.7._ 647 | */ 648 | function toInt216(int256 value) internal pure returns (int216) { 649 | require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits"); 650 | return int216(value); 651 | } 652 | 653 | /** 654 | * @dev Returns the downcasted int208 from int256, reverting on 655 | * overflow (when the input is less than smallest int208 or 656 | * greater than largest int208). 657 | * 658 | * Counterpart to Solidity's `int208` operator. 659 | * 660 | * Requirements: 661 | * 662 | * - input must fit into 208 bits 663 | * 664 | * _Available since v4.7._ 665 | */ 666 | function toInt208(int256 value) internal pure returns (int208) { 667 | require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits"); 668 | return int208(value); 669 | } 670 | 671 | /** 672 | * @dev Returns the downcasted int200 from int256, reverting on 673 | * overflow (when the input is less than smallest int200 or 674 | * greater than largest int200). 675 | * 676 | * Counterpart to Solidity's `int200` operator. 677 | * 678 | * Requirements: 679 | * 680 | * - input must fit into 200 bits 681 | * 682 | * _Available since v4.7._ 683 | */ 684 | function toInt200(int256 value) internal pure returns (int200) { 685 | require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits"); 686 | return int200(value); 687 | } 688 | 689 | /** 690 | * @dev Returns the downcasted int192 from int256, reverting on 691 | * overflow (when the input is less than smallest int192 or 692 | * greater than largest int192). 693 | * 694 | * Counterpart to Solidity's `int192` operator. 695 | * 696 | * Requirements: 697 | * 698 | * - input must fit into 192 bits 699 | * 700 | * _Available since v4.7._ 701 | */ 702 | function toInt192(int256 value) internal pure returns (int192) { 703 | require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits"); 704 | return int192(value); 705 | } 706 | 707 | /** 708 | * @dev Returns the downcasted int184 from int256, reverting on 709 | * overflow (when the input is less than smallest int184 or 710 | * greater than largest int184). 711 | * 712 | * Counterpart to Solidity's `int184` operator. 713 | * 714 | * Requirements: 715 | * 716 | * - input must fit into 184 bits 717 | * 718 | * _Available since v4.7._ 719 | */ 720 | function toInt184(int256 value) internal pure returns (int184) { 721 | require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits"); 722 | return int184(value); 723 | } 724 | 725 | /** 726 | * @dev Returns the downcasted int176 from int256, reverting on 727 | * overflow (when the input is less than smallest int176 or 728 | * greater than largest int176). 729 | * 730 | * Counterpart to Solidity's `int176` operator. 731 | * 732 | * Requirements: 733 | * 734 | * - input must fit into 176 bits 735 | * 736 | * _Available since v4.7._ 737 | */ 738 | function toInt176(int256 value) internal pure returns (int176) { 739 | require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits"); 740 | return int176(value); 741 | } 742 | 743 | /** 744 | * @dev Returns the downcasted int168 from int256, reverting on 745 | * overflow (when the input is less than smallest int168 or 746 | * greater than largest int168). 747 | * 748 | * Counterpart to Solidity's `int168` operator. 749 | * 750 | * Requirements: 751 | * 752 | * - input must fit into 168 bits 753 | * 754 | * _Available since v4.7._ 755 | */ 756 | function toInt168(int256 value) internal pure returns (int168) { 757 | require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits"); 758 | return int168(value); 759 | } 760 | 761 | /** 762 | * @dev Returns the downcasted int160 from int256, reverting on 763 | * overflow (when the input is less than smallest int160 or 764 | * greater than largest int160). 765 | * 766 | * Counterpart to Solidity's `int160` operator. 767 | * 768 | * Requirements: 769 | * 770 | * - input must fit into 160 bits 771 | * 772 | * _Available since v4.7._ 773 | */ 774 | function toInt160(int256 value) internal pure returns (int160) { 775 | require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits"); 776 | return int160(value); 777 | } 778 | 779 | /** 780 | * @dev Returns the downcasted int152 from int256, reverting on 781 | * overflow (when the input is less than smallest int152 or 782 | * greater than largest int152). 783 | * 784 | * Counterpart to Solidity's `int152` operator. 785 | * 786 | * Requirements: 787 | * 788 | * - input must fit into 152 bits 789 | * 790 | * _Available since v4.7._ 791 | */ 792 | function toInt152(int256 value) internal pure returns (int152) { 793 | require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits"); 794 | return int152(value); 795 | } 796 | 797 | /** 798 | * @dev Returns the downcasted int144 from int256, reverting on 799 | * overflow (when the input is less than smallest int144 or 800 | * greater than largest int144). 801 | * 802 | * Counterpart to Solidity's `int144` operator. 803 | * 804 | * Requirements: 805 | * 806 | * - input must fit into 144 bits 807 | * 808 | * _Available since v4.7._ 809 | */ 810 | function toInt144(int256 value) internal pure returns (int144) { 811 | require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits"); 812 | return int144(value); 813 | } 814 | 815 | /** 816 | * @dev Returns the downcasted int136 from int256, reverting on 817 | * overflow (when the input is less than smallest int136 or 818 | * greater than largest int136). 819 | * 820 | * Counterpart to Solidity's `int136` operator. 821 | * 822 | * Requirements: 823 | * 824 | * - input must fit into 136 bits 825 | * 826 | * _Available since v4.7._ 827 | */ 828 | function toInt136(int256 value) internal pure returns (int136) { 829 | require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits"); 830 | return int136(value); 831 | } 832 | 833 | /** 834 | * @dev Returns the downcasted int128 from int256, reverting on 835 | * overflow (when the input is less than smallest int128 or 836 | * greater than largest int128). 837 | * 838 | * Counterpart to Solidity's `int128` operator. 839 | * 840 | * Requirements: 841 | * 842 | * - input must fit into 128 bits 843 | * 844 | * _Available since v3.1._ 845 | */ 846 | function toInt128(int256 value) internal pure returns (int128) { 847 | require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits"); 848 | return int128(value); 849 | } 850 | 851 | /** 852 | * @dev Returns the downcasted int120 from int256, reverting on 853 | * overflow (when the input is less than smallest int120 or 854 | * greater than largest int120). 855 | * 856 | * Counterpart to Solidity's `int120` operator. 857 | * 858 | * Requirements: 859 | * 860 | * - input must fit into 120 bits 861 | * 862 | * _Available since v4.7._ 863 | */ 864 | function toInt120(int256 value) internal pure returns (int120) { 865 | require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits"); 866 | return int120(value); 867 | } 868 | 869 | /** 870 | * @dev Returns the downcasted int112 from int256, reverting on 871 | * overflow (when the input is less than smallest int112 or 872 | * greater than largest int112). 873 | * 874 | * Counterpart to Solidity's `int112` operator. 875 | * 876 | * Requirements: 877 | * 878 | * - input must fit into 112 bits 879 | * 880 | * _Available since v4.7._ 881 | */ 882 | function toInt112(int256 value) internal pure returns (int112) { 883 | require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits"); 884 | return int112(value); 885 | } 886 | 887 | /** 888 | * @dev Returns the downcasted int104 from int256, reverting on 889 | * overflow (when the input is less than smallest int104 or 890 | * greater than largest int104). 891 | * 892 | * Counterpart to Solidity's `int104` operator. 893 | * 894 | * Requirements: 895 | * 896 | * - input must fit into 104 bits 897 | * 898 | * _Available since v4.7._ 899 | */ 900 | function toInt104(int256 value) internal pure returns (int104) { 901 | require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits"); 902 | return int104(value); 903 | } 904 | 905 | /** 906 | * @dev Returns the downcasted int96 from int256, reverting on 907 | * overflow (when the input is less than smallest int96 or 908 | * greater than largest int96). 909 | * 910 | * Counterpart to Solidity's `int96` operator. 911 | * 912 | * Requirements: 913 | * 914 | * - input must fit into 96 bits 915 | * 916 | * _Available since v4.7._ 917 | */ 918 | function toInt96(int256 value) internal pure returns (int96) { 919 | require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits"); 920 | return int96(value); 921 | } 922 | 923 | /** 924 | * @dev Returns the downcasted int88 from int256, reverting on 925 | * overflow (when the input is less than smallest int88 or 926 | * greater than largest int88). 927 | * 928 | * Counterpart to Solidity's `int88` operator. 929 | * 930 | * Requirements: 931 | * 932 | * - input must fit into 88 bits 933 | * 934 | * _Available since v4.7._ 935 | */ 936 | function toInt88(int256 value) internal pure returns (int88) { 937 | require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits"); 938 | return int88(value); 939 | } 940 | 941 | /** 942 | * @dev Returns the downcasted int80 from int256, reverting on 943 | * overflow (when the input is less than smallest int80 or 944 | * greater than largest int80). 945 | * 946 | * Counterpart to Solidity's `int80` operator. 947 | * 948 | * Requirements: 949 | * 950 | * - input must fit into 80 bits 951 | * 952 | * _Available since v4.7._ 953 | */ 954 | function toInt80(int256 value) internal pure returns (int80) { 955 | require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits"); 956 | return int80(value); 957 | } 958 | 959 | /** 960 | * @dev Returns the downcasted int72 from int256, reverting on 961 | * overflow (when the input is less than smallest int72 or 962 | * greater than largest int72). 963 | * 964 | * Counterpart to Solidity's `int72` operator. 965 | * 966 | * Requirements: 967 | * 968 | * - input must fit into 72 bits 969 | * 970 | * _Available since v4.7._ 971 | */ 972 | function toInt72(int256 value) internal pure returns (int72) { 973 | require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits"); 974 | return int72(value); 975 | } 976 | 977 | /** 978 | * @dev Returns the downcasted int64 from int256, reverting on 979 | * overflow (when the input is less than smallest int64 or 980 | * greater than largest int64). 981 | * 982 | * Counterpart to Solidity's `int64` operator. 983 | * 984 | * Requirements: 985 | * 986 | * - input must fit into 64 bits 987 | * 988 | * _Available since v3.1._ 989 | */ 990 | function toInt64(int256 value) internal pure returns (int64) { 991 | require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits"); 992 | return int64(value); 993 | } 994 | 995 | /** 996 | * @dev Returns the downcasted int56 from int256, reverting on 997 | * overflow (when the input is less than smallest int56 or 998 | * greater than largest int56). 999 | * 1000 | * Counterpart to Solidity's `int56` operator. 1001 | * 1002 | * Requirements: 1003 | * 1004 | * - input must fit into 56 bits 1005 | * 1006 | * _Available since v4.7._ 1007 | */ 1008 | function toInt56(int256 value) internal pure returns (int56) { 1009 | require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits"); 1010 | return int56(value); 1011 | } 1012 | 1013 | /** 1014 | * @dev Returns the downcasted int48 from int256, reverting on 1015 | * overflow (when the input is less than smallest int48 or 1016 | * greater than largest int48). 1017 | * 1018 | * Counterpart to Solidity's `int48` operator. 1019 | * 1020 | * Requirements: 1021 | * 1022 | * - input must fit into 48 bits 1023 | * 1024 | * _Available since v4.7._ 1025 | */ 1026 | function toInt48(int256 value) internal pure returns (int48) { 1027 | require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits"); 1028 | return int48(value); 1029 | } 1030 | 1031 | /** 1032 | * @dev Returns the downcasted int40 from int256, reverting on 1033 | * overflow (when the input is less than smallest int40 or 1034 | * greater than largest int40). 1035 | * 1036 | * Counterpart to Solidity's `int40` operator. 1037 | * 1038 | * Requirements: 1039 | * 1040 | * - input must fit into 40 bits 1041 | * 1042 | * _Available since v4.7._ 1043 | */ 1044 | function toInt40(int256 value) internal pure returns (int40) { 1045 | require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits"); 1046 | return int40(value); 1047 | } 1048 | 1049 | /** 1050 | * @dev Returns the downcasted int32 from int256, reverting on 1051 | * overflow (when the input is less than smallest int32 or 1052 | * greater than largest int32). 1053 | * 1054 | * Counterpart to Solidity's `int32` operator. 1055 | * 1056 | * Requirements: 1057 | * 1058 | * - input must fit into 32 bits 1059 | * 1060 | * _Available since v3.1._ 1061 | */ 1062 | function toInt32(int256 value) internal pure returns (int32) { 1063 | require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits"); 1064 | return int32(value); 1065 | } 1066 | 1067 | /** 1068 | * @dev Returns the downcasted int24 from int256, reverting on 1069 | * overflow (when the input is less than smallest int24 or 1070 | * greater than largest int24). 1071 | * 1072 | * Counterpart to Solidity's `int24` operator. 1073 | * 1074 | * Requirements: 1075 | * 1076 | * - input must fit into 24 bits 1077 | * 1078 | * _Available since v4.7._ 1079 | */ 1080 | function toInt24(int256 value) internal pure returns (int24) { 1081 | require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits"); 1082 | return int24(value); 1083 | } 1084 | 1085 | /** 1086 | * @dev Returns the downcasted int16 from int256, reverting on 1087 | * overflow (when the input is less than smallest int16 or 1088 | * greater than largest int16). 1089 | * 1090 | * Counterpart to Solidity's `int16` operator. 1091 | * 1092 | * Requirements: 1093 | * 1094 | * - input must fit into 16 bits 1095 | * 1096 | * _Available since v3.1._ 1097 | */ 1098 | function toInt16(int256 value) internal pure returns (int16) { 1099 | require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits"); 1100 | return int16(value); 1101 | } 1102 | 1103 | /** 1104 | * @dev Returns the downcasted int8 from int256, reverting on 1105 | * overflow (when the input is less than smallest int8 or 1106 | * greater than largest int8). 1107 | * 1108 | * Counterpart to Solidity's `int8` operator. 1109 | * 1110 | * Requirements: 1111 | * 1112 | * - input must fit into 8 bits 1113 | * 1114 | * _Available since v3.1._ 1115 | */ 1116 | function toInt8(int256 value) internal pure returns (int8) { 1117 | require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits"); 1118 | return int8(value); 1119 | } 1120 | 1121 | /** 1122 | * @dev Converts an unsigned uint256 into a signed int256. 1123 | * 1124 | * Requirements: 1125 | * 1126 | * - input must be less than or equal to maxInt256. 1127 | * 1128 | * _Available since v3.0._ 1129 | */ 1130 | function toInt256(uint256 value) internal pure returns (int256) { 1131 | // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive 1132 | require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256"); 1133 | return int256(value); 1134 | } 1135 | } 1136 | --------------------------------------------------------------------------------