Overview
ETH Balance
0 ETH
Eth Value
$0.00Token Holdings
More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 7,403 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Produce Block | 20595491 | 1 hr ago | IN | 0 ETH | 0.00022083 | ||||
Rebalance | 20594548 | 4 hrs ago | IN | 0 ETH | 0.00028213 | ||||
Stake | 20594206 | 5 hrs ago | IN | 0 ETH | 0.00014058 | ||||
Produce Block | 20593605 | 7 hrs ago | IN | 0 ETH | 0.00057381 | ||||
Produce Block | 20593286 | 8 hrs ago | IN | 0 ETH | 0.00085183 | ||||
Deposit | 20593216 | 8 hrs ago | IN | 0 ETH | 0.00020555 | ||||
Rebalance | 20592754 | 10 hrs ago | IN | 0 ETH | 0.00031719 | ||||
Stake | 20592751 | 10 hrs ago | IN | 0 ETH | 0.00011375 | ||||
Withdraw | 20589974 | 19 hrs ago | IN | 0 ETH | 0.00011738 | ||||
Produce Block | 20589886 | 19 hrs ago | IN | 0 ETH | 0.00019998 | ||||
Deposit | 20589121 | 22 hrs ago | IN | 0 ETH | 0.00011117 | ||||
Rebalance | 20587363 | 28 hrs ago | IN | 0 ETH | 0.00024816 | ||||
Unstake | 20587361 | 28 hrs ago | IN | 0 ETH | 0.00013135 | ||||
Rebalance | 20583260 | 42 hrs ago | IN | 0 ETH | 0.00027558 | ||||
Produce Block | 20583178 | 42 hrs ago | IN | 0 ETH | 0.00024118 | ||||
Produce Block | 20583166 | 42 hrs ago | IN | 0 ETH | 0.00022505 | ||||
Produce Block | 20582786 | 43 hrs ago | IN | 0 ETH | 0.00022788 | ||||
Rebalance | 20581473 | 2 days ago | IN | 0 ETH | 0.0002649 | ||||
Produce Block | 20580684 | 2 days ago | IN | 0 ETH | 0.00020781 | ||||
Rebalance | 20579683 | 2 days ago | IN | 0 ETH | 0.00065153 | ||||
Produce Block | 20578102 | 2 days ago | IN | 0 ETH | 0.00059635 | ||||
Rebalance | 20577896 | 2 days ago | IN | 0 ETH | 0.00083707 | ||||
Stake | 20577893 | 2 days ago | IN | 0 ETH | 0.00067804 | ||||
Rebalance | 20575820 | 2 days ago | IN | 0 ETH | 0.00027662 | ||||
Produce Block | 20574941 | 2 days ago | IN | 0 ETH | 0.00019264 |
Advanced mode: Intended for advanced users or developers and will display all Internal Transactions including zero value transfers. Name tag integration is not available in advanced view.
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | ||||
---|---|---|---|---|---|---|---|
20595491 | 1 hr ago | 0 ETH | |||||
20595491 | 1 hr ago | 0 ETH | |||||
20595491 | 1 hr ago | 0 ETH | |||||
20595491 | 1 hr ago | 0 ETH | |||||
20595491 | 1 hr ago | 0 ETH | |||||
20595491 | 1 hr ago | 0 ETH | |||||
20594548 | 4 hrs ago | 0 ETH | |||||
20594548 | 4 hrs ago | 0 ETH | |||||
20594548 | 4 hrs ago | 0 ETH | |||||
20594548 | 4 hrs ago | 0 ETH | |||||
20594206 | 5 hrs ago | 0 ETH | |||||
20593605 | 7 hrs ago | 0 ETH | |||||
20593605 | 7 hrs ago | 0 ETH | |||||
20593605 | 7 hrs ago | 0 ETH | |||||
20593605 | 7 hrs ago | 0 ETH | |||||
20593605 | 7 hrs ago | 0 ETH | |||||
20593605 | 7 hrs ago | 0 ETH | |||||
20593286 | 8 hrs ago | 0 ETH | |||||
20593286 | 8 hrs ago | 0 ETH | |||||
20593286 | 8 hrs ago | 0 ETH | |||||
20593286 | 8 hrs ago | 0 ETH | |||||
20593286 | 8 hrs ago | 0 ETH | |||||
20593286 | 8 hrs ago | 0 ETH | |||||
20593216 | 8 hrs ago | 0 ETH | |||||
20593216 | 8 hrs ago | 0 ETH |
Loading...
Loading
Minimal Proxy Contract for 0x3f9a0b1a0b81473e051a26a039f730b28f02018b
Contract Name:
StakingPoolImpl
Compiler Version
v0.8.7+commit.e28d00a7
Contract Source Code (Solidity Standard Json-Input format)
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity ^0.8.0; import "./interfaces/StakingPool.sol"; import "./StakingPoolData.sol"; import "./StakingPoolManagementImpl.sol"; import "./StakingPoolProducerImpl.sol"; import "./StakingPoolStakingImpl.sol"; import "./StakingPoolUserImpl.sol"; import "./StakingPoolWorkerImpl.sol"; contract StakingPoolImpl is StakingPool, StakingPoolData, StakingPoolManagementImpl, StakingPoolProducerImpl, StakingPoolStakingImpl, StakingPoolUserImpl, StakingPoolWorkerImpl { constructor( address _ctsi, address _staking, address _workerManager, address _ens, uint256 _stakeLock ) StakingPoolManagementImpl(_ens) StakingPoolProducerImpl(_ctsi) StakingPoolStakingImpl(_ctsi, _staking) StakingPoolUserImpl(_ctsi, _stakeLock) StakingPoolWorkerImpl(_workerManager) {} function initialize(address _fee, address _pos) external override initializer { __Pausable_init(); __Ownable_init(); __StakingPoolProducer_init(_fee, _pos); __StakingPoolStaking_init(); __StakingPoolManagementImpl_init(); } /// @notice updates the internal settings for important pieces of the Cartesi PoS system function update() external override onlyOwner { address _pos = factory.getPoS(); __StakingPoolWorkerImpl_update(_pos); } function transferOwnership(address newOwner) public override(StakingPool, OwnableUpgradeable) { OwnableUpgradeable.transferOwnership(newOwner); } }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. /// @title Interface PoS pragma solidity >=0.7.0 <0.9.0; interface IPoS { /// @notice Produce a block /// @param _index the index of the instance of pos you want to interact with /// @dev this function can only be called by a worker, user never calls it directly function produceBlock(uint256 _index) external returns (bool); /// @notice Get reward manager address /// @param _index index of instance /// @return address of instance's RewardManager function getRewardManagerAddress(uint256 _index) external view returns (address); /// @notice Get block selector address /// @param _index index of instance /// @return address of instance's block selector function getBlockSelectorAddress(uint256 _index) external view returns (address); /// @notice Get block selector index /// @param _index index of instance /// @return index of instance's block selector function getBlockSelectorIndex(uint256 _index) external view returns (uint256); /// @notice Get staking address /// @param _index index of instance /// @return address of instance's staking contract function getStakingAddress(uint256 _index) external view returns (address); /// @notice Get state of a particular instance /// @param _index index of instance /// @param _user address of user /// @return bool if user is eligible to produce next block /// @return address of user that was chosen to build the block /// @return current reward paid by the network for that block function getState(uint256 _index, address _user) external view returns ( bool, address, uint256 ); function terminate(uint256 _index) external; }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. /// @title Interface RewardManager pragma solidity >=0.7.0 <0.9.0; interface IRewardManager { /// @notice Rewards address /// @param _address address be rewarded /// @param _amount reward /// @dev only the pos contract can call this function reward(address _address, uint256 _amount) external; /// @notice Get RewardManager's balance function getBalance() external view returns (uint256); /// @notice Get current reward amount function getCurrentReward() external view returns (uint256); }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. /// @title Interface Staking pragma solidity >=0.7.0 <0.9.0; interface IStaking { /// @notice Returns total amount of tokens counted as stake /// @param _userAddress user to retrieve staked balance from /// @return finalized staked of _userAddress function getStakedBalance(address _userAddress) external view returns (uint256); /// @notice Returns the timestamp when next deposit can be finalized /// @return timestamp of when finalizeStakes() is callable function getMaturingTimestamp(address _userAddress) external view returns (uint256); /// @notice Returns the timestamp when next withdraw can be finalized /// @return timestamp of when finalizeWithdraw() is callable function getReleasingTimestamp(address _userAddress) external view returns (uint256); /// @notice Returns the balance waiting/ready to be matured /// @return amount that will get staked after finalization function getMaturingBalance(address _userAddress) external view returns (uint256); /// @notice Returns the balance waiting/ready to be released /// @return amount that will get withdrew after finalization function getReleasingBalance(address _userAddress) external view returns (uint256); /// @notice Deposit CTSI to be staked. The money will turn into staked /// balance after timeToStake days /// @param _amount The amount of tokens that are gonna be deposited. function stake(uint256 _amount) external; /// @notice Remove tokens from staked balance. The money can /// be released after timeToRelease seconds, if the /// function withdraw is called. /// @param _amount The amount of tokens that are gonna be unstaked. function unstake(uint256 _amount) external; /// @notice Transfer tokens to user's wallet. /// @param _amount The amount of tokens that are gonna be transferred. function withdraw(uint256 _amount) external; // events /// @notice CTSI tokens were deposited, they count as stake after _maturationDate /// @param user address of msg.sender /// @param amount amount deposited for staking /// @param maturationDate date when the stake can be finalized event Stake(address indexed user, uint256 amount, uint256 maturationDate); /// @notice Unstake tokens, moving them to releasing structure /// @param user address of msg.sender /// @param amount amount of tokens to be released /// @param maturationDate date when the tokens can be withdrew event Unstake(address indexed user, uint256 amount, uint256 maturationDate); /// @notice Withdraw process was finalized /// @param user address of msg.sender /// @param amount amount of tokens withdrawn event Withdraw(address indexed user, uint256 amount); }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. /// @title Interface WorkerManager /// @author Danilo Tuler pragma solidity >=0.7.0 <0.9.0; interface IWorkerManagerAuthManager { /// @notice Asks the worker to work for the sender. Sender needs to pay something. /// @param workerAddress address of the worker function hire(address payable workerAddress) external payable; /// @notice Called by the user to cancel a job offer /// @param workerAddress address of the worker node function cancelHire(address workerAddress) external; /// @notice Called by the user to retire his worker. /// @param workerAddress address of the worker to be retired /// @dev this also removes all authorizations in place function retire(address payable workerAddress) external; /// @notice Gives worker permission to act on a DApp /// @param _workerAddress address of the worker node to given permission /// @param _dappAddress address of the dapp that permission will be given to function authorize(address _workerAddress, address _dappAddress) external; /// @notice Called by the worker to accept the job function acceptJob() external; /// @notice Called by the worker to reject a job offer function rejectJob() external payable; }
pragma solidity >=0.8.4; interface ENS { // Logged when the owner of a node assigns a new owner to a subnode. event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); // Logged when the owner of a node transfers ownership to a new account. event Transfer(bytes32 indexed node, address owner); // Logged when the resolver for a node changes. event NewResolver(bytes32 indexed node, address resolver); // Logged when the TTL of a node changes event NewTTL(bytes32 indexed node, uint64 ttl); // Logged when an operator is added or removed. event ApprovalForAll(address indexed owner, address indexed operator, bool approved); function setRecord(bytes32 node, address owner, address resolver, uint64 ttl) external virtual; function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external virtual; function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external virtual returns(bytes32); function setResolver(bytes32 node, address resolver) external virtual; function setOwner(bytes32 node, address owner) external virtual; function setTTL(bytes32 node, uint64 ttl) external virtual; function setApprovalForAll(address operator, bool approved) external virtual; function owner(bytes32 node) external virtual view returns (address); function resolver(bytes32 node) external virtual view returns (address); function ttl(bytes32 node) external virtual view returns (uint64); function recordExists(bytes32 node) external virtual view returns (bool); function isApprovedForAll(address owner, address operator) external virtual view returns (bool); }
pragma solidity >=0.8.4; import "./ENS.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "../root/Controllable.sol"; abstract contract NameResolver { function setName(bytes32 node, string memory name) public virtual; } bytes32 constant lookup = 0x3031323334353637383961626364656600000000000000000000000000000000; bytes32 constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; // namehash('addr.reverse') contract ReverseRegistrar is Ownable, Controllable { ENS public ens; NameResolver public defaultResolver; event ReverseClaimed(address indexed addr, bytes32 indexed node); /** * @dev Constructor * @param ensAddr The address of the ENS registry. * @param resolverAddr The address of the default reverse resolver. */ constructor(ENS ensAddr, NameResolver resolverAddr) { ens = ensAddr; defaultResolver = resolverAddr; // Assign ownership of the reverse record to our deployer ReverseRegistrar oldRegistrar = ReverseRegistrar( ens.owner(ADDR_REVERSE_NODE) ); if (address(oldRegistrar) != address(0x0)) { oldRegistrar.claim(msg.sender); } } modifier authorised(address addr) { require( addr == msg.sender || controllers[msg.sender] || ens.isApprovedForAll(addr, msg.sender) || ownsContract(addr), "Caller is not a controller or authorised by address or the address itself" ); _; } /** * @dev Transfers ownership of the reverse ENS record associated with the * calling account. * @param owner The address to set as the owner of the reverse record in ENS. * @return The ENS node hash of the reverse record. */ function claim(address owner) public returns (bytes32) { return _claimWithResolver(msg.sender, owner, address(0x0)); } /** * @dev Transfers ownership of the reverse ENS record associated with the * calling account. * @param addr The reverse record to set * @param owner The address to set as the owner of the reverse record in ENS. * @return The ENS node hash of the reverse record. */ function claimForAddr(address addr, address owner) public authorised(addr) returns (bytes32) { return _claimWithResolver(addr, owner, address(0x0)); } /** * @dev Transfers ownership of the reverse ENS record associated with the * calling account. * @param owner The address to set as the owner of the reverse record in ENS. * @param resolver The address of the resolver to set; 0 to leave unchanged. * @return The ENS node hash of the reverse record. */ function claimWithResolver(address owner, address resolver) public returns (bytes32) { return _claimWithResolver(msg.sender, owner, resolver); } /** * @dev Transfers ownership of the reverse ENS record specified with the * address provided * @param addr The reverse record to set * @param owner The address to set as the owner of the reverse record in ENS. * @param resolver The address of the resolver to set; 0 to leave unchanged. * @return The ENS node hash of the reverse record. */ function claimWithResolverForAddr( address addr, address owner, address resolver ) public authorised(addr) returns (bytes32) { return _claimWithResolver(addr, owner, resolver); } /** * @dev Sets the `name()` record for the reverse ENS record associated with * the calling account. First updates the resolver to the default reverse * resolver if necessary. * @param name The name to set for this address. * @return The ENS node hash of the reverse record. */ function setName(string memory name) public returns (bytes32) { bytes32 node = _claimWithResolver( msg.sender, address(this), address(defaultResolver) ); defaultResolver.setName(node, name); return node; } /** * @dev Sets the `name()` record for the reverse ENS record associated with * the account provided. First updates the resolver to the default reverse * resolver if necessary. * Only callable by controllers and authorised users * @param addr The reverse record to set * @param owner The owner of the reverse node * @param name The name to set for this address. * @return The ENS node hash of the reverse record. */ function setNameForAddr( address addr, address owner, string memory name ) public authorised(addr) returns (bytes32) { bytes32 node = _claimWithResolver( addr, address(this), address(defaultResolver) ); defaultResolver.setName(node, name); ens.setSubnodeOwner(ADDR_REVERSE_NODE, sha3HexAddress(addr), owner); return node; } /** * @dev Returns the node hash for a given account's reverse records. * @param addr The address to hash * @return The ENS node hash. */ function node(address addr) public pure returns (bytes32) { return keccak256( abi.encodePacked(ADDR_REVERSE_NODE, sha3HexAddress(addr)) ); } /** * @dev An optimised function to compute the sha3 of the lower-case * hexadecimal representation of an Ethereum address. * @param addr The address to hash * @return ret The SHA3 hash of the lower-case hexadecimal encoding of the * input address. */ function sha3HexAddress(address addr) private pure returns (bytes32 ret) { assembly { for { let i := 40 } gt(i, 0) { } { i := sub(i, 1) mstore8(i, byte(and(addr, 0xf), lookup)) addr := div(addr, 0x10) i := sub(i, 1) mstore8(i, byte(and(addr, 0xf), lookup)) addr := div(addr, 0x10) } ret := keccak256(0, 40) } } /* Internal functions */ function _claimWithResolver( address addr, address owner, address resolver ) internal returns (bytes32) { bytes32 label = sha3HexAddress(addr); bytes32 node = keccak256(abi.encodePacked(ADDR_REVERSE_NODE, label)); address currentResolver = ens.resolver(node); bool shouldUpdateResolver = (resolver != address(0x0) && resolver != currentResolver); address newResolver = shouldUpdateResolver ? resolver : currentResolver; ens.setSubnodeRecord(ADDR_REVERSE_NODE, label, owner, newResolver, 0); emit ReverseClaimed(addr, node); return node; } function ownsContract(address addr) internal view returns (bool) { try Ownable(addr).owner() returns (address owner) { return owner == msg.sender; } catch { return false; } } }
pragma solidity ^0.8.4; import "@openzeppelin/contracts/access/Ownable.sol"; contract Controllable is Ownable { mapping(address => bool) public controllers; event ControllerChanged(address indexed controller, bool enabled); modifier onlyController { require( controllers[msg.sender], "Controllable: Caller is not a controller" ); _; } function setController(address controller, bool enabled) public onlyOwner { controllers[controller] = enabled; emit ControllerChanged(controller, enabled); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal initializer { __Context_init_unchained(); __Ownable_init_unchained(); } function __Ownable_init_unchained() internal initializer { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Modifier to protect an initializer function from being invoked twice. */ modifier initializer() { require(_initializing || !_initialized, "Initializable: contract is already initialized"); bool isTopLevelCall = !_initializing; if (isTopLevelCall) { _initializing = true; _initialized = true; } _; if (isTopLevelCall) { _initializing = false; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal initializer { __Context_init_unchained(); __Pausable_init_unchained(); } function __Pausable_init_unchained() internal initializer { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal initializer { __Context_init_unchained(); } function __Context_init_unchained() internal initializer { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } uint256[50] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _setOwner(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _setOwner(newOwner); } function _setOwner(address newOwner) private { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import "@cartesi/pos/contracts/IPoS.sol"; import "./utils/WadRayMath.sol"; contract StakingPoolData is Initializable, PausableUpgradeable, OwnableUpgradeable { using WadRayMath for uint256; uint256 public shares; // total number of shares uint256 public amount; // amount of staked tokens (no matter where it is) uint256 public requiredLiquidity; // amount of required tokens for withdraw requests IPoS public pos; struct UserBalance { uint256 balance; // amount of free tokens belonging to this user uint256 shares; // amount of shares belonging to this user uint256 depositTimestamp; // timestamp of when user deposited for the last time } mapping(address => UserBalance) public userBalance; function amountToShares(uint256 _amount) public view returns (uint256) { if (amount == 0) { // no shares yet, return 1 to 1 ratio return _amount.wad2ray(); } return _amount.wmul(shares).wdiv(amount); } function sharesToAmount(uint256 _shares) public view returns (uint256) { if (shares == 0) { // no shares yet, return 1 to 1 ratio return _shares.ray2wad(); } return _shares.rmul(amount).rdiv(shares); } }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity ^0.8.0; import "@ensdomains/ens-contracts/contracts/registry/ReverseRegistrar.sol"; import "@ensdomains/ens-contracts/contracts/registry/ENS.sol"; import "./interfaces/StakingPoolManagement.sol"; import "./interfaces/StakingPoolFactory.sol"; import "./StakingPoolData.sol"; contract StakingPoolManagementImpl is StakingPoolManagement, StakingPoolData { bytes32 private constant ADDR_REVERSE_NODE = 0x91d1777781884d03a6757a803996e38de2a42967fb37eeaca72729271025a9e2; ENS public immutable ens; StakingPoolFactory public factory; // all immutable variables can stay at the constructor constructor(address _ens) initializer { require(_ens != address(0), "parameter can not be zero address"); ens = ENS(_ens); // make sure reference code is pause so no one stake to it _pause(); } function __StakingPoolManagementImpl_init() internal { factory = StakingPoolFactory(msg.sender); } /// @notice sets a name for the pool using ENS service function setName(string memory name) external override onlyOwner { ReverseRegistrar ensReverseRegistrar = ReverseRegistrar( ens.owner(ADDR_REVERSE_NODE) ); // call the ENS reverse registrar resolving pool address to name ensReverseRegistrar.setName(name); // emit event, for subgraph processing emit StakingPoolRenamed(name); } /// @notice pauses new staking on the pool function pause() external override onlyOwner { _pause(); } /// @notice unpauses new staking on the pool function unpause() external override onlyOwner { _unpause(); } }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@cartesi/pos/contracts/IPoS.sol"; import "@cartesi/pos/contracts/IRewardManager.sol"; import "./interfaces/Fee.sol"; import "./interfaces/StakingPoolProducer.sol"; import "./StakingPoolData.sol"; contract StakingPoolProducerImpl is StakingPoolProducer, StakingPoolData { IERC20 public immutable ctsi; Fee public fee; constructor(address _ctsi) { ctsi = IERC20(_ctsi); } function __StakingPoolProducer_init(address _fee, address _pos) internal { fee = Fee(_fee); pos = IPoS(_pos); } /// @notice routes produceBlock to POS contract and /// updates internal states of the pool /// @return true when everything went fine function produceBlock(uint256 _index) external override returns (bool) { IRewardManager rewardManager = IRewardManager( pos.getRewardManagerAddress(_index) ); // get block reward uint256 reward = rewardManager.getCurrentReward(); // produce block in the PoS require( pos.produceBlock(_index), "StakingPoolProducerImpl: failed to produce block" ); // calculate pool commission uint256 commission = fee.getCommission(_index, reward); require( commission <= reward, "StakingPoolProducerImpl: commission is greater than block reward" ); uint256 remainingReward = reward - commission; // this is a safety check // if commission is over the reward amount, it will underflow // increase pool amount, this will change the pool exchange rate amount += remainingReward; // send commission directly to pool owner if (commission > 0) { require( ctsi.transfer(owner(), commission), "StakingPoolProducerImpl: failed to transfer commission" ); } // remainingReward is part of the balance, so it will automatically be staked by StakingPoolStakingImpl emit BlockProduced(reward, commission); return true; } }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@cartesi/pos/contracts/IStaking.sol"; import "./interfaces/StakingPoolStaking.sol"; import "./StakingPoolData.sol"; /// @notice This contract takes care of the interaction between the pool and the staking contract /// It makes sure that there is enough liquidity in the pool to fullfil all unstake request from /// users, by requesting to withdraw or unstake from Staking contract. /// The remaining balance is staked. contract StakingPoolStakingImpl is StakingPoolStaking, StakingPoolData { IERC20 private immutable ctsi; IStaking private immutable staking; constructor(address _ctsi, address _staking) { ctsi = IERC20(_ctsi); staking = IStaking(_staking); } function __StakingPoolStaking_init() internal { require( ctsi.approve(address(staking), type(uint256).max), "Failed to approve CTSI for staking contract" ); } function rebalance() external override { // get amounts (uint256 _stake, uint256 _unstake, uint256 _withdraw) = amounts(); if (_stake > 0) { // we can stake staking.stake(_stake); } if (_unstake > 0) { // we need to provide liquidity staking.unstake(_unstake); } if (_withdraw > 0) { // we need to provide liquidity staking.withdraw(_withdraw); } } function amounts() public view override returns ( uint256 stake, uint256 unstake, uint256 withdraw ) { // get this contract balance first uint256 balance = ctsi.balanceOf(address(this)); if (balance > requiredLiquidity) { // we have spare tokens we can stake // check if there is anything already maturing, to avoid reset the maturation clock uint256 maturing = staking.getMaturingBalance(address(this)); if (maturing == 0) { // nothing is maturing, we can stake the balance, preserving the liquidity stake = balance - requiredLiquidity; } } else if (requiredLiquidity > balance) { // we don't have enough tokens to provide liquidity uint256 missingLiquidity = requiredLiquidity - balance; // let's first check releasing balance uint256 releasing = staking.getReleasingBalance(address(this)); if (releasing > 0) { // some is already releasing // let's check timestamp to see if we can withdrawn it uint256 timestamp = staking.getReleasingTimestamp( address(this) ); if (timestamp < block.timestamp) { // there it is, let's grab it withdraw = releasing; } // requiredLiquidity may be more than what is already releasing // but we won't unstake more to not reset the clock } else { // no unstake maturing, let's queue some unstake = missingLiquidity; } } else { // balance is exactly required liquidity, we can't move any tokens around } } }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./interfaces/StakingPoolUser.sol"; import "./StakingPoolData.sol"; contract StakingPoolUserImpl is StakingPoolUser, StakingPoolData { IERC20 private immutable ctsi; uint256 public immutable lockTime; /// @dev Constructor /// @param _ctsi The contract that provides the staking pool's token /// @param _lockTime The user deposit lock period constructor(address _ctsi, uint256 _lockTime) { ctsi = IERC20(_ctsi); lockTime = _lockTime; } function deposit(uint256 _amount) external override whenNotPaused { // transfer tokens from caller to this contract // user must have approved the transfer a priori // tokens will be lying around, until actually staked by pool owner at a later time require( _amount > 0, "StakingPoolUserImpl: amount must be greater than 0" ); // add tokens to user's balance UserBalance storage user = userBalance[msg.sender]; user.balance += _amount; // reset deposit timestamp user.depositTimestamp = block.timestamp; // reserve the balance as required liquidity (don't stake to Staking) requiredLiquidity += _amount; require( ctsi.transferFrom(msg.sender, address(this), _amount), "StakingPoolUserImpl: failed to transfer tokens" ); // emit event containing user and amount emit Deposit(msg.sender, _amount, block.timestamp + lockTime); } /// @notice Stake an amount of tokens, immediately earning pool shares in returns /// @param _amount amount of tokens to convert from user's balance function stake(uint256 _amount) external override whenNotPaused { // get user balance UserBalance storage user = userBalance[msg.sender]; // transfer tokens from caller to this contract // user must have approved the transfer a priori // tokens will be lying around, until actually staked by pool owner at a later time require( _amount > 0, "StakingPoolUserImpl: amount must be greater than 0" ); require( _amount <= user.balance, "StakingPoolUserImpl: not enough tokens available for staking" ); // check if user can already stake or if it's too early require( block.timestamp >= user.depositTimestamp + lockTime, "StakingPoolUserImpl: not enough time has passed since last deposit" ); // calculate amount of shares as of now uint256 _shares = amountToShares(_amount); // make sure he get at least one share (rounding errors) require( _shares > 0, "StakingPoolUserImpl: stake not enough to emit 1 share" ); // allocate new shares to user, immediately user.shares += _shares; user.balance -= _amount; // increase total shares and amount (not changing share value) amount += _amount; shares += _shares; // remove from required liquidity, as it's moving to Staking requiredLiquidity -= _amount; // emit event containing user, amount, shares and unlock time emit Stake(msg.sender, _amount, _shares); } /// @notice allow for users to defined exactly how many shares they /// want to unstake. Estimated value is then emitted on Unstake event function unstake(uint256 _shares) external override { UserBalance storage user = userBalance[msg.sender]; // check if shares is valid value require(_shares > 0, "StakingPoolUserImpl: invalid amount of shares"); // check if user has enough shares to unstake require( user.shares >= _shares, "StakingPoolUserImpl: insufficient shares" ); // reduce user number of shares user.shares -= _shares; // calculate amount of tokens from shares uint256 _amount = sharesToAmount(_shares); // reduce total shares and amount shares -= _shares; amount -= _amount; // add amount user can withdraw (if available) user.balance += _amount; // increase required liquidity requiredLiquidity += _amount; // emit event containing user, amount and shares emit Unstake(msg.sender, _amount, _shares); } /// @notice Transfer tokens back to calling user wallet /// @dev this will transfer all free tokens for the calling user function withdraw(uint256 _amount) external override { UserBalance storage user = userBalance[msg.sender]; // check user released value require( user.balance > 0, "StakingPoolUserImpl: no balance to withdraw" ); // clear user released value user.balance -= _amount; // if _amount > user.balance this will revert // decrease required liquidity requiredLiquidity -= _amount; // if _amount > requiredLiquidity this will revert // transfer token back to user require( ctsi.transfer(msg.sender, _amount), "StakingPoolUserImpl: failed to transfer tokens" ); // emit event containing user and token amount emit Withdraw(msg.sender, _amount); } function getWithdrawBalance() external view override returns (uint256) { UserBalance storage user = userBalance[msg.sender]; // get maximum amount user can withdraw (his balance) uint256 _amount = user.balance; // check contract balance uint256 balance = ctsi.balanceOf(address(this)); // he can withdraw whatever is available at the contract, up to his balance return balance >= _amount ? _amount : balance; } }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity ^0.8.0; import "@cartesi/pos/contracts/IWorkerManagerAuthManager.sol"; import "./interfaces/StakingPoolWorker.sol"; import "./StakingPoolData.sol"; contract StakingPoolWorkerImpl is StakingPoolWorker, StakingPoolData { IWorkerManagerAuthManager immutable workerManager; // all immutable variables can stay at the constructor constructor(address _workerManager) { require( _workerManager != address(0), "parameter can not be zero address" ); workerManager = IWorkerManagerAuthManager(_workerManager); } receive() external payable {} function __StakingPoolWorkerImpl_update(address _pos) internal { workerManager.authorize(address(this), _pos); pos = IPoS(_pos); } /// @notice allows for the pool to act on its own behalf when producing blocks. function selfhire() external payable override { // pool needs to be both user and worker workerManager.hire{value: msg.value}(payable(address(this))); workerManager.authorize(address(this), address(pos)); workerManager.acceptJob(); payable(msg.sender).transfer(msg.value); } /// @notice Asks the worker to work for the sender. Sender needs to pay something. /// @param workerAddress address of the worker function hire(address payable workerAddress) external payable override onlyOwner { workerManager.hire{value: msg.value}(workerAddress); workerManager.authorize(workerAddress, address(pos)); } /// @notice Called by the user to cancel a job offer /// @param workerAddress address of the worker node function cancelHire(address workerAddress) external override onlyOwner { workerManager.cancelHire(workerAddress); } /// @notice Called by the user to retire his worker. /// @param workerAddress address of the worker to be retired /// @dev this also removes all authorizations in place function retire(address payable workerAddress) external override onlyOwner { workerManager.retire(workerAddress); } }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity >=0.7.0 <0.9.0; /// @title Calculator of pool owner commission for each block reward /// @author Danilo Tuler /// @notice This provides flexibility for different commission models interface Fee { /// @notice calculates the total amount of the reward that will be directed to the pool owner /// @return amount of tokens taken by the pool owner as commission function getCommission(uint256 posIndex, uint256 rewardAmount) external view returns (uint256); }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity >=0.7.0; import "./StakingPoolManagement.sol"; import "./StakingPoolProducer.sol"; import "./StakingPoolStaking.sol"; import "./StakingPoolUser.sol"; import "./StakingPoolWorker.sol"; /// @title Staking Pool interface /// @author Danilo Tuler /// @notice This interface aggregates all facets of a staking pool. /// It is broken down into the following sub-interfaces: /// - StakingPoolManagement: management operations on the pool, called by the owner /// - StakingPoolProducer: operations related to block production /// - StakingPoolStaking: interaction between the pool and the staking contract /// - StakingPoolUser: interaction between the pool users and the pool /// - StakingPoolWorker: interaction between the pool and the worker node interface StakingPool is StakingPoolManagement, StakingPoolProducer, StakingPoolStaking, StakingPoolUser, StakingPoolWorker { /// @notice initialize pool (from reference) function initialize(address fee, address _pos) external; /// @notice Transfer ownership of pool to its deployer function transferOwnership(address newOwner) external; /// @notice updates the internal settings for important pieces of the Cartesi PoS system function update() external; }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity >=0.7.0; interface StakingPoolFactory { /// @notice Creates a new staking pool using a flat commission model /// emits NewFlatRateCommissionStakingPool with the parameters of the new pool /// @return new pool address function createFlatRateCommission(uint256 commission) external payable returns (address); /// @notice Creates a new staking pool using a gas tax commission model /// emits NewGasTaxCommissionStakingPool with the parameters of the new pool /// @return new pool address function createGasTaxCommission(uint256 gas) external payable returns (address); /// @notice Returns configuration for the working pools of the current version /// @return _pos address for the PoS contract function getPoS() external view returns (address _pos); /// @notice Event emmited when a pool is created /// @param pool address of the new pool /// @param fee address of the commission contract event NewFlatRateCommissionStakingPool(address indexed pool, address fee); /// @notice Event emmited when a pool is created /// @param pool address of the new pool /// @param fee address of thhe commission contract event NewGasTaxCommissionStakingPool(address indexed pool, address fee); }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity >=0.7.0; interface StakingPoolManagement { /// @notice sets a name for the pool using ENS service function setName(string memory name) external; /// @notice pauses new staking on the pool function pause() external; /// @notice unpauses new staking on the pool function unpause() external; /// @notice Event emmited when a pool is rename event StakingPoolRenamed(string name); }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity >=0.7.0; /// @title Interaction between a pool and the PoS block production. /// @author Danilo Tuler /// @notice This interface provides an opportunity to handle the necessary logic /// after a block is produced. /// A commission is taken from the block reward, and the remaining stays in the pool, /// raising the pool share value, and being further staked. interface StakingPoolProducer { /// @notice routes produceBlock to POS contract and /// updates internal states of the pool /// @return true when everything went fine function produceBlock(uint256 _index) external returns (bool); /// @notice this event is emitted at every produceBlock call /// reward is the block reward /// commission is how much CTSI is directed to the pool owner event BlockProduced(uint256 reward, uint256 commission); }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity >=0.7.0; /// @title Interaction between a pool and the staking contract /// @author Danilo Tuler /// @notice This interface models all interactions between a pool and the staking contract, /// including staking, unstaking and withdrawing. /// Tokens staked by pool users will stay at the pool until the pool owner decides to /// stake them in the staking contract. On the other hand, tokens unstaked by pool users /// are added to a required liquidity accumulator, and must be unstaked and withdrawn from /// the staking contract. interface StakingPoolStaking { /// @notice Move tokens from pool to staking or vice-versa, according to required liquidity. /// If the pool has more liquidity then necessary, it stakes tokens. /// If the pool has less liquidity then necessary, and has not started an unstake, it unstakes. /// If the pool has less liquity than necessary, and has started an unstake, it withdraws if possible. function rebalance() external; /// @notice provide information for offchain about the amount for each /// staking operation on the main Staking contract /// @return stake amount of tokens that can be staked /// @return unstake amount of tokens that must be unstaked to add liquidity /// @return withdraw amount of tokens that can be withdrawn to add liquidity function amounts() external view returns ( uint256 stake, uint256 unstake, uint256 withdraw ); }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity >=0.7.0; /// @title Interaction between a pool user and a pool /// @author Danilo Tuler /// @notice This interface models all interactions between a pool user and a pool, /// including staking, unstaking and withdrawing. A pool user always holds pool shares. /// When a user stakes tokens, he immediately receive shares. When he unstakes shares /// he is asking to release tokens. Those tokens need to be withdrawn by an additional /// call to withdraw() interface StakingPoolUser { /// @notice Deposit tokens to user pool balance /// @param amount amount of token deposited in the pool function deposit(uint256 amount) external; /// @notice Stake an amount of tokens, immediately earning pool shares in returns /// @param amount amount of tokens to convert to shares function stake(uint256 amount) external; /// @notice Unstake an specified amount of shares of the calling user /// @dev Shares are immediately converted to tokens, and added to the pool liquidity requirement function unstake(uint256 shares) external; /// @notice Transfer tokens back to calling user wallet /// @dev this will transfer tokens from user pool account to user's wallet function withdraw(uint256 amount) external; /// @notice Returns the amount of tokens that can be immediately withdrawn by the calling user /// @dev there is no way to know the exact time in the future the requested tokens will be available /// @return the amount of tokens that can be immediately withdrawn by the calling user function getWithdrawBalance() external returns (uint256); /// @notice Tokens were deposited, available for staking or withdrawal /// @param user address of msg.sender /// @param amount amount of tokens deposited by the user /// @param stakeTimestamp instant when the amount can be staked event Deposit(address indexed user, uint256 amount, uint256 stakeTimestamp); /// @notice Tokens were deposited, they count as shares immediatly /// @param user address of msg.sender /// @param amount amount deposited by the user /// @param shares number of shares emitted for user event Stake(address indexed user, uint256 amount, uint256 shares); /// @notice Request to unstake tokens. Additional liquidity requested for the pool /// @param user address of msg.sender /// @param amount amount of tokens to be released /// @param shares number of shares being liquidated event Unstake(address indexed user, uint256 amount, uint256 shares); /// @notice Withdraw performed by a user /// @param user address of msg.sender /// @param amount amount of tokens withdrawn event Withdraw(address indexed user, uint256 amount); }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. pragma solidity >=0.7.0; interface StakingPoolWorker { /// @notice allows for the pool to act on its own behalf when producing blocks. function selfhire() external payable; /// @notice Asks the worker to work for the sender. Sender needs to pay something. /// @param workerAddress address of the worker function hire(address payable workerAddress) external payable; /// @notice Called by the user to cancel a job offer /// @param workerAddress address of the worker node function cancelHire(address workerAddress) external; /// @notice Called by the user to retire his worker. /// @param workerAddress address of the worker to be retired /// @dev this also removes all authorizations in place function retire(address payable workerAddress) external; }
// Copyright 2021 Cartesi Pte. Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); you may not use // this file except in compliance with the License. You may obtain a copy of the // License at http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software distributed // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR // CONDITIONS OF ANY KIND, either express or implied. See the License for the // specific language governing permissions and limitations under the License. /// @title Wad and Ray Math library /// @dev Math operations for wads (fixed point with 18 digits) and rays (fixed points with 27 digits) pragma solidity ^0.8.0; library WadRayMath { uint256 internal constant WAD = 1e18; uint256 internal constant RAY = 1e27; uint256 internal constant RATIO = 1e9; function wmul(uint256 a, uint256 b) internal pure returns (uint256) { return ((WAD / 2) + (a * b)) / WAD; } function wdiv(uint256 a, uint256 b) internal pure returns (uint256) { uint256 halfB = b / 2; return (halfB + (a * WAD)) / b; } function rmul(uint256 a, uint256 b) internal pure returns (uint256) { return ((RAY / 2) + (a * b)) / RAY; } function rdiv(uint256 a, uint256 b) internal pure returns (uint256) { uint256 halfB = b / 2; return (halfB + (a * RAY)) / b; } function ray2wad(uint256 a) internal pure returns (uint256) { uint256 halfRatio = RATIO / 2; return (halfRatio + a) / RATIO; } function wad2ray(uint256 a) internal pure returns (uint256) { return a * RATIO; } }
{ "evmVersion": "london", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
[{"inputs":[{"internalType":"address","name":"_ctsi","type":"address"},{"internalType":"address","name":"_staking","type":"address"},{"internalType":"address","name":"_workerManager","type":"address"},{"internalType":"address","name":"_ens","type":"address"},{"internalType":"uint256","name":"_stakeLock","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"commission","type":"uint256"}],"name":"BlockProduced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakeTimestamp","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"}],"name":"StakingPoolRenamed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Unstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"amount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"amountToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"amounts","outputs":[{"internalType":"uint256","name":"stake","type":"uint256"},{"internalType":"uint256","name":"unstake","type":"uint256"},{"internalType":"uint256","name":"withdraw","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"workerAddress","type":"address"}],"name":"cancelHire","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ctsi","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ens","outputs":[{"internalType":"contract ENS","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract StakingPoolFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"contract Fee","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWithdrawBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"workerAddress","type":"address"}],"name":"hire","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_fee","type":"address"},{"internalType":"address","name":"_pos","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pos","outputs":[{"internalType":"contract IPoS","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"produceBlock","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requiredLiquidity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"workerAddress","type":"address"}],"name":"retire","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"selfhire","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"setName","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"sharesToAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_shares","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"update","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userBalance","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"depositTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.145571 | 1,027,944.5499 | $149,638.68 |
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.