Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 13,121 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim And Lock | 20359851 | 156 days ago | IN | 0 ETH | 0.00057578 | ||||
Claim And Lock | 20359121 | 156 days ago | IN | 0 ETH | 0.00112173 | ||||
Claim And Lock | 20358967 | 156 days ago | IN | 0 ETH | 0.00064046 | ||||
Claim And Lock | 20358944 | 156 days ago | IN | 0 ETH | 0.00057126 | ||||
Claim And Lock | 20358593 | 156 days ago | IN | 0 ETH | 0.00146842 | ||||
Claim And Lock | 20358544 | 156 days ago | IN | 0 ETH | 0.00148996 | ||||
Claim And Lock | 20358527 | 156 days ago | IN | 0 ETH | 0.00168109 | ||||
Claim And Lock | 20358525 | 156 days ago | IN | 0 ETH | 0.00165959 | ||||
Claim And Lock | 20357946 | 156 days ago | IN | 0 ETH | 0.00135471 | ||||
Claim And Lock | 20356920 | 157 days ago | IN | 0 ETH | 0.00231594 | ||||
Claim And Lock | 20356699 | 157 days ago | IN | 0 ETH | 0.00946256 | ||||
Claim And Lock | 20356173 | 157 days ago | IN | 0 ETH | 0.00081893 | ||||
Claim And Lock | 20355370 | 157 days ago | IN | 0 ETH | 0.00082716 | ||||
Claim And Lock | 20353860 | 157 days ago | IN | 0 ETH | 0.00055238 | ||||
Claim And Lock | 20353816 | 157 days ago | IN | 0 ETH | 0.00056788 | ||||
Claim And Lock | 20351451 | 157 days ago | IN | 0 ETH | 0.00046679 | ||||
Claim And Lock | 20350224 | 157 days ago | IN | 0 ETH | 0.00060573 | ||||
Claim And Lock | 20349571 | 158 days ago | IN | 0 ETH | 0.00084203 | ||||
Claim And Lock | 20348374 | 158 days ago | IN | 0 ETH | 0.00114687 | ||||
Claim And Lock | 20348086 | 158 days ago | IN | 0 ETH | 0.00089843 | ||||
Claim And Lock | 20347152 | 158 days ago | IN | 0 ETH | 0.00076253 | ||||
Claim And Lock | 20346901 | 158 days ago | IN | 0 ETH | 0.00066868 | ||||
Claim And Lock | 20346337 | 158 days ago | IN | 0 ETH | 0.00064016 | ||||
Claim And Lock | 20345452 | 158 days ago | IN | 0 ETH | 0.00052126 | ||||
Claim And Lock | 20343431 | 158 days ago | IN | 0 ETH | 0.00089856 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
Relocker
Compiler Version
v0.8.12+commit.f00d7308
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.12; import {ERC20} from "@rari-capital/solmate/src/tokens/ERC20.sol"; import {SafeTransferLib} from "@rari-capital/solmate/src/utils/SafeTransferLib.sol"; import {RLBTRFLY} from "contracts/core/RLBTRFLY.sol"; library Common { struct Claim { address token; address account; uint256 amount; bytes32[] merkleProof; } } interface IRewardDistributor { function claim(Common.Claim[] calldata claims) external; } contract Relocker { using SafeTransferLib for ERC20; ERC20 public immutable btrfly; RLBTRFLY public immutable rlBtrfly; IRewardDistributor public immutable rewardDistributor; event Relock(address indexed account, uint256 amount); error ZeroAddress(); error ZeroAmount(); constructor( address _btrfly, address _rlBtrfly, address _rewardDistributor ) { if (_btrfly == address(0)) revert ZeroAddress(); if (_rlBtrfly == address(0)) revert ZeroAddress(); if (_rewardDistributor == address(0)) revert ZeroAddress(); btrfly = ERC20(_btrfly); rlBtrfly = RLBTRFLY(_rlBtrfly); rewardDistributor = IRewardDistributor(_rewardDistributor); btrfly.approve(_rlBtrfly, type(uint256).max); } /** @notice Claim rewards based on the specified metadata and lock amount as rlBtrfly @notice Use msg.sender not account parameter since relock is explicit action @param claims Claim[] List of claim metadata @param amount uint256 Amount to relock, cheaper to calculate offchain */ function claimAndLock(Common.Claim[] calldata claims, uint256 amount) external { if (amount == 0) revert ZeroAmount(); rewardDistributor.claim(claims); btrfly.safeTransferFrom(msg.sender, address(this), amount); rlBtrfly.lock(msg.sender, amount); emit Relock(msg.sender, amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*/////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*/////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*/////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*/////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*/////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*/////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*/////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { bytes32 digest = keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) ) ); address recoveredAddress = ecrecover(digest, v, r, s); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*/////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @author Modified from Gnosis (https://github.com/gnosis/gp-v2-contracts/blob/main/src/contracts/libraries/GPv2SafeERC20.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. library SafeTransferLib { /*/////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool callStatus; assembly { // Transfer the ETH and store if it succeeded or not. callStatus := call(gas(), to, amount, 0, 0, 0, 0) } require(callStatus, "ETH_TRANSFER_FAILED"); } /*/////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool callStatus; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata to memory piece by piece: mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) // Begin with the function selector. mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "from" argument. mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value. // Call the token and store if it succeeded or not. // We use 100 because the calldata length is 4 + 32 * 3. callStatus := call(gas(), token, 0, freeMemoryPointer, 100, 0, 0) } require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool callStatus; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata to memory piece by piece: mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) // Begin with the function selector. mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value. // Call the token and store if it succeeded or not. // We use 68 because the calldata length is 4 + 32 * 2. callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0) } require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool callStatus; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata to memory piece by piece: mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) // Begin with the function selector. mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value. // Call the token and store if it succeeded or not. // We use 68 because the calldata length is 4 + 32 * 2. callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0) } require(didLastOptionalReturnCallSucceed(callStatus), "APPROVE_FAILED"); } /*/////////////////////////////////////////////////////////////// INTERNAL HELPER LOGIC //////////////////////////////////////////////////////////////*/ function didLastOptionalReturnCallSucceed(bool callStatus) private pure returns (bool success) { assembly { // Get how many bytes the call returned. let returnDataSize := returndatasize() // If the call reverted: if iszero(callStatus) { // Copy the revert message into memory. returndatacopy(0, 0, returnDataSize) // Revert with the same message. revert(0, returnDataSize) } switch returnDataSize case 32 { // Copy the return data into memory. returndatacopy(0, 0, returnDataSize) // Set success to whether it returned true. success := iszero(iszero(mload(0))) } case 0 { // There was no return data. success := 1 } default { // It returned some malformed input. success := 0 } } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.12; import {ReentrancyGuard} from "@rari-capital/solmate/src/utils/ReentrancyGuard.sol"; import {ERC20} from "@rari-capital/solmate/src/tokens/ERC20.sol"; import {SafeTransferLib} from "@rari-capital/solmate/src/utils/SafeTransferLib.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; /// @title RLBTRFLY /// @author ████ /** @notice Partially adapted from Convex's CvxLockerV2 contract with some modifications and optimizations for the BTRFLY V2 requirements */ contract RLBTRFLY is ReentrancyGuard, Ownable { using SafeTransferLib for ERC20; /** @notice Lock balance details @param amount uint224 Locked amount in the lock @param unlockTime uint32 Unlock time of the lock */ struct LockedBalance { uint224 amount; uint32 unlockTime; } /** @notice Balance details @param locked uint224 Overall locked amount @param nextUnlockIndex uint32 Index of earliest next unlock @param lockedBalances LockedBalance[] List of locked balances data */ struct Balance { uint224 locked; uint32 nextUnlockIndex; LockedBalance[] lockedBalances; } // 1 epoch = 1 week uint32 public constant EPOCH_DURATION = 1 weeks; // Full lock duration = 16 epochs uint256 public constant LOCK_DURATION = 16 * EPOCH_DURATION; ERC20 public immutable btrflyV2; uint256 public lockedSupply; mapping(address => Balance) public balances; bool public isShutdown; string public constant name = "Revenue-Locked BTRFLY"; string public constant symbol = "rlBTRFLY"; uint8 public constant decimals = 18; event Shutdown(); event Locked( address indexed account, uint256 indexed epoch, uint256 amount ); event Withdrawn(address indexed account, uint256 amount, bool relock); error ZeroAddress(); error ZeroAmount(); error IsShutdown(); error InvalidNumber(uint256 value); /** @param _btrflyV2 address BTRFLYV2 token address */ constructor(address _btrflyV2) { if (_btrflyV2 == address(0)) revert ZeroAddress(); btrflyV2 = ERC20(_btrflyV2); } /** @notice Emergency method to shutdown the current locker contract which also force-unlock all locked tokens */ function shutdown() external onlyOwner { if (isShutdown) revert IsShutdown(); isShutdown = true; emit Shutdown(); } /** @notice Locked balance of the specified account including those with expired locks @param account address Account @return amount uint256 Amount */ function lockedBalanceOf(address account) external view returns (uint256 amount) { return balances[account].locked; } /** @notice Balance of the specified account by only including tokens in active locks @param account address Account @return amount uint256 Amount */ function balanceOf(address account) external view returns (uint256 amount) { // Using storage as it's actually cheaper than allocating a new memory based variable Balance storage userBalance = balances[account]; LockedBalance[] storage locks = userBalance.lockedBalances; uint256 nextUnlockIndex = userBalance.nextUnlockIndex; amount = balances[account].locked; uint256 locksLength = locks.length; // Skip all old records for (uint256 i = nextUnlockIndex; i < locksLength; ++i) { if (locks[i].unlockTime <= block.timestamp) { amount -= locks[i].amount; } else { break; } } // Remove amount locked in the next epoch if ( locksLength > 0 && uint256(locks[locksLength - 1].unlockTime) - LOCK_DURATION > getCurrentEpoch() ) { amount -= locks[locksLength - 1].amount; } return amount; } /** @notice Pending locked amount at the specified account @param account address Account @return amount uint256 Amount */ function pendingLockOf(address account) external view returns (uint256 amount) { LockedBalance[] storage locks = balances[account].lockedBalances; uint256 locksLength = locks.length; if ( locksLength > 0 && uint256(locks[locksLength - 1].unlockTime) - LOCK_DURATION > getCurrentEpoch() ) { return locks[locksLength - 1].amount; } return 0; } /** @notice Locked balances details for the specifed account @param account address Account @return total uint256 Total amount @return unlockable uint256 Unlockable amount @return locked uint256 Locked amount @return lockData LockedBalance[] List of active locks */ function lockedBalances(address account) external view returns ( uint256 total, uint256 unlockable, uint256 locked, LockedBalance[] memory lockData ) { Balance storage userBalance = balances[account]; LockedBalance[] storage locks = userBalance.lockedBalances; uint256 nextUnlockIndex = userBalance.nextUnlockIndex; uint256 idx; for (uint256 i = nextUnlockIndex; i < locks.length; ++i) { if (locks[i].unlockTime > block.timestamp) { if (idx == 0) { lockData = new LockedBalance[](locks.length - i); } lockData[idx] = locks[i]; locked += lockData[idx].amount; ++idx; } else { unlockable += locks[i].amount; } } return (userBalance.locked, unlockable, locked, lockData); } /** @notice Get current epoch @return uint256 Current epoch */ function getCurrentEpoch() public view returns (uint256) { return (block.timestamp / EPOCH_DURATION) * EPOCH_DURATION; } /** @notice Locked tokens cannot be withdrawn for the entire lock duration and are eligible to receive rewards @param account address Account @param amount uint256 Amount */ function lock(address account, uint256 amount) external nonReentrant { if (account == address(0)) revert ZeroAddress(); if (amount == 0) revert ZeroAmount(); btrflyV2.safeTransferFrom(msg.sender, address(this), amount); _lock(account, amount); } /** @notice Perform the actual lock @param account address Account @param amount uint256 Amount */ function _lock(address account, uint256 amount) internal { if (isShutdown) revert IsShutdown(); Balance storage balance = balances[account]; uint224 lockAmount = _toUint224(amount); balance.locked += lockAmount; lockedSupply += lockAmount; uint256 lockEpoch = getCurrentEpoch() + EPOCH_DURATION; uint256 unlockTime = lockEpoch + LOCK_DURATION; LockedBalance[] storage locks = balance.lockedBalances; uint256 idx = locks.length; // If the latest user lock is smaller than this lock, add a new entry to the end of the list // else, append it to the latest user lock if (idx == 0 || locks[idx - 1].unlockTime < unlockTime) { locks.push( LockedBalance({ amount: lockAmount, unlockTime: _toUint32(unlockTime) }) ); } else { locks[idx - 1].amount += lockAmount; } emit Locked(account, lockEpoch, amount); } /** @notice Withdraw all currently locked tokens where the unlock time has passed @param account address Account @param relock bool Whether should relock @param withdrawTo address Target receiver */ function _processExpiredLocks( address account, bool relock, address withdrawTo ) internal { // Using storage as it's actually cheaper than allocating a new memory based variable Balance storage userBalance = balances[account]; LockedBalance[] storage locks = userBalance.lockedBalances; uint224 locked; uint256 length = locks.length; if (isShutdown || locks[length - 1].unlockTime <= block.timestamp) { locked = userBalance.locked; userBalance.nextUnlockIndex = _toUint32(length); } else { // Using nextUnlockIndex to reduce the number of loops uint32 nextUnlockIndex = userBalance.nextUnlockIndex; for (uint256 i = nextUnlockIndex; i < length; ++i) { // Unlock time must be less or equal to time if (locks[i].unlockTime > block.timestamp) break; // Add to cumulative amounts locked += locks[i].amount; ++nextUnlockIndex; } // Update the account's next unlock index userBalance.nextUnlockIndex = nextUnlockIndex; } if (locked == 0) revert ZeroAmount(); // Update user balances and total supplies userBalance.locked -= locked; lockedSupply -= locked; emit Withdrawn(account, locked, relock); // Relock or return to user if (relock) { _lock(withdrawTo, locked); } else { btrflyV2.safeTransfer(withdrawTo, locked); } } /** @notice Withdraw expired locks to a different address @param to address Target receiver */ function withdrawExpiredLocksTo(address to) external nonReentrant { if (to == address(0)) revert ZeroAddress(); _processExpiredLocks(msg.sender, false, to); } /** @notice Withdraw/relock all currently locked tokens where the unlock time has passed @param relock bool Whether should relock */ function processExpiredLocks(bool relock) external nonReentrant { _processExpiredLocks(msg.sender, relock, msg.sender); } /** @notice Validate and cast a uint256 integer to uint224 @param value uint256 Value @return uint224 Casted value */ function _toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) revert InvalidNumber(value); return uint224(value); } /** @notice Validate and cast a uint256 integer to uint32 @param value uint256 Value @return uint32 Casted value */ function _toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) revert InvalidNumber(value); return uint32(value); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Gas optimized reentrancy protection for smart contracts. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol) /// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol) abstract contract ReentrancyGuard { uint256 private reentrancyStatus = 1; modifier nonReentrant() { require(reentrancyStatus == 1, "REENTRANCY"); reentrancyStatus = 2; _; reentrancyStatus = 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) 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() { _transferOwnership(_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 { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) 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; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_btrfly","type":"address"},{"internalType":"address","name":"_rlBtrfly","type":"address"},{"internalType":"address","name":"_rewardDistributor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Relock","type":"event"},{"inputs":[],"name":"btrfly","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"internalType":"struct Common.Claim[]","name":"claims","type":"tuple[]"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimAndLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardDistributor","outputs":[{"internalType":"contract IRewardDistributor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rlBtrfly","outputs":[{"internalType":"contract RLBTRFLY","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60e060405234801561001057600080fd5b5060405161075a38038061075a83398101604081905261002f91610151565b6001600160a01b0383166100565760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b03821661007d5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0381166100a45760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b03838116608081905283821660a081905291831660c05260405163095ea7b360e01b8152600481019290925260001960248301529063095ea7b3906044016020604051808303816000875af1158015610108573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061012c9190610194565b505050506101bd565b80516001600160a01b038116811461014c57600080fd5b919050565b60008060006060848603121561016657600080fd5b61016f84610135565b925061017d60208501610135565b915061018b60408501610135565b90509250925092565b6000602082840312156101a657600080fd5b815180151581146101b657600080fd5b9392505050565b60805160a05160c05161055c6101fe6000396000818160ae015261012c01526000818160d501526101e8015260008181605601526101a2015261055c6000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c8063841560051461005157806387151b8814610094578063acc2166a146100a9578063da43af9f146100d0575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b6100a76100a2366004610365565b6100f7565b005b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6100787f000000000000000000000000000000000000000000000000000000000000000081565b8061011557604051631f2a200560e01b815260040160405180910390fd5b604051632434331360e11b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906348686626906101639086908690600401610432565b600060405180830381600087803b15801561017d57600080fd5b505af1158015610191573d6000803e3d6000fd5b506101cc9250506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169050333084610286565b60405163282d3fdf60e01b8152336004820152602481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063282d3fdf90604401600060405180830381600087803b15801561023457600080fd5b505af1158015610248573d6000803e3d6000fd5b50506040518381523392507f31bd6ac63b078494589dfd74b11e70e90a86974bf5d950759a67a6e81b03d78f915060200160405180910390a2505050565b60006040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b038416602482015282604482015260008060648360008a5af19150506102d08161031e565b6103175760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b604482015260640160405180910390fd5b5050505050565b60003d8261033057806000803e806000fd5b8060208114610348578015610359576000925061035e565b816000803e6000511515925061035e565b600192505b5050919050565b60008060006040848603121561037a57600080fd5b833567ffffffffffffffff8082111561039257600080fd5b818601915086601f8301126103a657600080fd5b8135818111156103b557600080fd5b8760208260051b85010111156103ca57600080fd5b6020928301989097509590910135949350505050565b80356001600160a01b03811681146103f757600080fd5b919050565b81835260006001600160fb1b0383111561041557600080fd5b8260051b8083602087013760009401602001938452509192915050565b60208082528181018390526000906040808401600586811b8601830188865b8981101561051757888303603f190185528135368c9003607e1901811261047757600080fd5b8b0160806001600160a01b038061048d846103e0565b1686528061049c8b85016103e0565b168a870152508782013588860152606080830135601e198436030181126104c257600080fd5b8301803567ffffffffffffffff8111156104db57600080fd5b80891b36038513156104ec57600080fd5b8383890152610500848901828e85016103fc565b998c01999750505093890193505050600101610451565b5090999850505050505050505056fea2646970667358221220060427c0346095de923b698785484ff654d15579d451e7188c26e213f573dbee64736f6c634300080c0033000000000000000000000000c55126051b22ebb829d00368f4b12bde432de5da000000000000000000000000742b70151cd3bc7ab598aaff1d54b90c3ebc6027000000000000000000000000d7807e5752b368a6a64b76828aaff0750522a76e
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061004c5760003560e01c8063841560051461005157806387151b8814610094578063acc2166a146100a9578063da43af9f146100d0575b600080fd5b6100787f000000000000000000000000c55126051b22ebb829d00368f4b12bde432de5da81565b6040516001600160a01b03909116815260200160405180910390f35b6100a76100a2366004610365565b6100f7565b005b6100787f000000000000000000000000d7807e5752b368a6a64b76828aaff0750522a76e81565b6100787f000000000000000000000000742b70151cd3bc7ab598aaff1d54b90c3ebc602781565b8061011557604051631f2a200560e01b815260040160405180910390fd5b604051632434331360e11b81526001600160a01b037f000000000000000000000000d7807e5752b368a6a64b76828aaff0750522a76e16906348686626906101639086908690600401610432565b600060405180830381600087803b15801561017d57600080fd5b505af1158015610191573d6000803e3d6000fd5b506101cc9250506001600160a01b037f000000000000000000000000c55126051b22ebb829d00368f4b12bde432de5da169050333084610286565b60405163282d3fdf60e01b8152336004820152602481018290527f000000000000000000000000742b70151cd3bc7ab598aaff1d54b90c3ebc60276001600160a01b03169063282d3fdf90604401600060405180830381600087803b15801561023457600080fd5b505af1158015610248573d6000803e3d6000fd5b50506040518381523392507f31bd6ac63b078494589dfd74b11e70e90a86974bf5d950759a67a6e81b03d78f915060200160405180910390a2505050565b60006040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b038416602482015282604482015260008060648360008a5af19150506102d08161031e565b6103175760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b604482015260640160405180910390fd5b5050505050565b60003d8261033057806000803e806000fd5b8060208114610348578015610359576000925061035e565b816000803e6000511515925061035e565b600192505b5050919050565b60008060006040848603121561037a57600080fd5b833567ffffffffffffffff8082111561039257600080fd5b818601915086601f8301126103a657600080fd5b8135818111156103b557600080fd5b8760208260051b85010111156103ca57600080fd5b6020928301989097509590910135949350505050565b80356001600160a01b03811681146103f757600080fd5b919050565b81835260006001600160fb1b0383111561041557600080fd5b8260051b8083602087013760009401602001938452509192915050565b60208082528181018390526000906040808401600586811b8601830188865b8981101561051757888303603f190185528135368c9003607e1901811261047757600080fd5b8b0160806001600160a01b038061048d846103e0565b1686528061049c8b85016103e0565b168a870152508782013588860152606080830135601e198436030181126104c257600080fd5b8301803567ffffffffffffffff8111156104db57600080fd5b80891b36038513156104ec57600080fd5b8383890152610500848901828e85016103fc565b998c01999750505093890193505050600101610451565b5090999850505050505050505056fea2646970667358221220060427c0346095de923b698785484ff654d15579d451e7188c26e213f573dbee64736f6c634300080c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c55126051b22ebb829d00368f4b12bde432de5da000000000000000000000000742b70151cd3bc7ab598aaff1d54b90c3ebc6027000000000000000000000000d7807e5752b368a6a64b76828aaff0750522a76e
-----Decoded View---------------
Arg [0] : _btrfly (address): 0xc55126051B22eBb829D00368f4B12Bde432de5Da
Arg [1] : _rlBtrfly (address): 0x742B70151cd3Bc7ab598aAFF1d54B90c3ebC6027
Arg [2] : _rewardDistributor (address): 0xd7807E5752B368A6a64b76828Aaff0750522a76E
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000c55126051b22ebb829d00368f4b12bde432de5da
Arg [1] : 000000000000000000000000742b70151cd3bc7ab598aaff1d54b90c3ebc6027
Arg [2] : 000000000000000000000000d7807e5752b368a6a64b76828aaff0750522a76e
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.