Contract 0xf6b81e637a51444688d5fbe26d938b7485de9be8 1

 
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x0579020caa7b8a7fdd6b51aa2f849fbbe421c44365d2c0345adb641ec78b5ea60x60806040203221182022-08-15 14:33:5446 days 25 mins ago0x88532f5e88f6a1ccd9e64681acc63416594000f4 IN  Create: Bond0 ETH0.001888222328 ETH
[ Download CSV Export 
Latest 6 internal transactions
Parent Txn Hash Block From To Value
0xac1e2b2f9045ba0799394eabf3a740f78dfd91d9f1d677eac5f7642bc9e0af11203221792022-08-15 14:34:4546 days 24 mins ago 0xad961758441a99147478c594d70868c1104eb071 0xf6b81e637a51444688d5fbe26d938b7485de9be80 ETH
0xac1e2b2f9045ba0799394eabf3a740f78dfd91d9f1d677eac5f7642bc9e0af11203221792022-08-15 14:34:4546 days 24 mins ago 0xf6b81e637a51444688d5fbe26d938b7485de9be8 0xad961758441a99147478c594d70868c1104eb0710 ETH
0xac1e2b2f9045ba0799394eabf3a740f78dfd91d9f1d677eac5f7642bc9e0af11203221792022-08-15 14:34:4546 days 24 mins ago 0xf6b81e637a51444688d5fbe26d938b7485de9be8 0xad961758441a99147478c594d70868c1104eb0710 ETH
0xac1e2b2f9045ba0799394eabf3a740f78dfd91d9f1d677eac5f7642bc9e0af11203221792022-08-15 14:34:4546 days 24 mins ago 0xad961758441a99147478c594d70868c1104eb071 0xf6b81e637a51444688d5fbe26d938b7485de9be80 ETH
0xac1e2b2f9045ba0799394eabf3a740f78dfd91d9f1d677eac5f7642bc9e0af11203221792022-08-15 14:34:4546 days 24 mins ago 0xad961758441a99147478c594d70868c1104eb071 0xf6b81e637a51444688d5fbe26d938b7485de9be80 ETH
0xac1e2b2f9045ba0799394eabf3a740f78dfd91d9f1d677eac5f7642bc9e0af11203221792022-08-15 14:34:4546 days 24 mins ago 0xad961758441a99147478c594d70868c1104eb071 0xf6b81e637a51444688d5fbe26d938b7485de9be80 ETH
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Bond

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 20000 runs

Other Settings:
default evmVersion, GNU AGPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Arbiscan on 2022-08-15
*/

// SPDX-License-Identifier: AGPL-3.0-only
// Proxy Bonds are a modified gradual dutch auction mechanism for protocols to sell their native tokens.

/// @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);
    }
}

// [VOTES] The Votes Module is the ERC20 token that represents voting power in the network.

error TargetNotAContract(address target_);
error InvalidKeycode(Keycode keycode_);
error InvalidRole(Role role_);

function toKeycode(bytes5 keycode_) pure returns (Keycode) {
    return Keycode.wrap(keycode_);
}

function fromKeycode(Keycode keycode_) pure returns (bytes5) {
    return Keycode.unwrap(keycode_);
}

function toRole(bytes32 role_) pure returns (Role) {
    return Role.wrap(role_);
}

function fromRole(Role role_) pure returns (bytes32) {
    return Role.unwrap(role_);
}

function ensureContract(address target_) view {
    uint256 size;
    assembly("memory-safe") {
        size := extcodesize(target_)
    }
    if (size == 0) revert TargetNotAContract(target_);
}

function ensureValidKeycode(Keycode keycode_) pure {
    bytes5 unwrapped = Keycode.unwrap(keycode_);

    for (uint256 i = 0; i < 5; ) {
        bytes1 char = unwrapped[i];

        if (char < 0x41 || char > 0x5A) revert InvalidKeycode(keycode_); // A-Z only

        unchecked {
            i++;
        }
    }
}

function ensureValidRole(Role role_) pure {
    bytes32 unwrapped = Role.unwrap(role_);

    for (uint256 i = 0; i < 32; ) {
        bytes1 char = unwrapped[i];
        if ((char < 0x61 || char > 0x7A) && char != 0x00) {
            revert InvalidRole(role_); // a-z only
        }
        unchecked {
            i++;
        }
    }
}

// ######################## ~ ERRORS ~ ########################

// KERNEL ADAPTER

error KernelAdapter_OnlyKernel(address caller_);

// MODULE

error Module_PolicyNotAuthorized(address policy_);

// POLICY

error Policy_OnlyRole(Role role_);
error Policy_ModuleDoesNotExist(Keycode keycode_);

// KERNEL

error Kernel_OnlyExecutor(address caller_);
error Kernel_OnlyAdmin(address caller_);
error Kernel_ModuleAlreadyInstalled(Keycode module_);
error Kernel_InvalidModuleUpgrade(Keycode module_);
error Kernel_PolicyAlreadyApproved(address policy_);
error Kernel_PolicyNotApproved(address policy_);
error Kernel_AddressAlreadyHasRole(address addr_, Role role_);
error Kernel_AddressDoesNotHaveRole(address addr_, Role role_);
error Kernel_RoleDoesNotExist(Role role_);

// ######################## ~ GLOBAL TYPES ~ ########################

enum Actions {
    InstallModule,
    UpgradeModule,
    ActivatePolicy,
    DeactivatePolicy,
    ChangeExecutor,
    ChangeAdmin,
    MigrateKernel
}

struct Instruction {
    Actions action;
    address target;
}

struct Permissions {
    Keycode keycode;
    bytes4 funcSelector;
}

type Keycode is bytes5;
type Role is bytes32;

// ######################## ~ MODULE ABSTRACT ~ ########################

abstract contract KernelAdapter {
    Kernel public kernel;

    constructor(Kernel kernel_) {
        kernel = kernel_;
    }

    modifier onlyKernel() {
        if (msg.sender != address(kernel)) revert KernelAdapter_OnlyKernel(msg.sender);
        _;
    }

    function changeKernel(Kernel newKernel_) external onlyKernel {
        kernel = newKernel_;
    }
}

abstract contract Module is KernelAdapter {
    event PermissionSet(bytes4 funcSelector_, address policy_, bool permission_);

    constructor(Kernel kernel_) KernelAdapter(kernel_) {}

    modifier permissioned() {
        if (!kernel.modulePermissions(KEYCODE(), Policy(msg.sender), msg.sig))
            revert Module_PolicyNotAuthorized(msg.sender);
        _;
    }

    function KEYCODE() public pure virtual returns (Keycode);

    /// @notice Specify which version of a module is being implemented.
    /// @dev Minor version change retains interface. Major version upgrade indicates
    /// @dev breaking change to the interface.
    function VERSION() external pure virtual returns (uint8 major, uint8 minor) {}

    /// @notice Initialization function for the module.
    /// @dev This function is called when the module is installed or upgraded by the kernel.
    /// @dev Used to encompass any upgrade logic. Must be gated by onlyKernel.
    function INIT() external virtual onlyKernel {}
}

abstract contract Policy is KernelAdapter  {

    bool public isActive;

    constructor(Kernel kernel_) KernelAdapter(kernel_) {}

    modifier onlyRole(bytes32 role_) {
        Role role = toRole(role_);
        if(!kernel.hasRole(msg.sender, role))
            revert Policy_OnlyRole(role);
        _;
    }

    function configureDependencies() external virtual onlyKernel returns (Keycode[] memory dependencies) {}

    function requestPermissions() external view virtual onlyKernel returns (Permissions[] memory requests) {}

    function getModuleAddress(Keycode keycode_) internal view returns (address) {
        address moduleForKeycode = address(kernel.getModuleForKeycode(keycode_));
        if (moduleForKeycode == address(0)) revert Policy_ModuleDoesNotExist(keycode_);
        return moduleForKeycode;
    }

    /// @notice Function to let kernel grant or revoke active status
    function setActiveStatus(bool activate_) external onlyKernel {
        isActive = activate_;
    }
}

contract Kernel {
    // ######################## ~ VARS ~ ########################
    address public executor;
    address public admin;

    // ######################## ~ DEPENDENCY MANAGEMENT ~ ########################

    // Module Management
    Keycode[] public allKeycodes;
    mapping(Keycode => Module) public getModuleForKeycode; // get contract for module keycode
    mapping(Module => Keycode) public getKeycodeForModule; // get module keycode for contract
    
    // Module dependents data. Manages module dependencies for policies
    mapping(Keycode => Policy[]) public moduleDependents;
    mapping(Keycode => mapping(Policy => uint256)) public getDependentIndex;

    // Module <> Policy Permissions. Policy -> Keycode -> Function Selector -> Permission
    mapping(Keycode => mapping(Policy => mapping(bytes4 => bool))) public modulePermissions; // for policy addr, check if they have permission to call the function int he module

    // List of all active policies
    Policy[] public activePolicies;
    mapping(Policy => uint256) public getPolicyIndex;

    // Policy roles data
    mapping(address => mapping(Role => bool)) public hasRole;
    mapping(Role => bool) public isRole;

    // ######################## ~ EVENTS ~ ########################

    event PermissionsUpdated(
        Keycode indexed keycode_,
        Policy indexed policy_,
        bytes4 funcSelector_,
        bool granted_
    );
    event RoleGranted(Role indexed role_, address indexed addr_);
    event RoleRevoked(Role indexed role_, address indexed addr_);
    event ActionExecuted(Actions indexed action_, address indexed target_);

    // ######################## ~ BODY ~ ########################

    constructor() {
        executor = msg.sender;
        admin = msg.sender;
    }

    // ######################## ~ MODIFIERS ~ ########################

    // Role reserved for governor or any executing address
    modifier onlyExecutor() {
        if (msg.sender != executor) revert Kernel_OnlyExecutor(msg.sender);
        _;
    }

    // Role for managing policy roles
    modifier onlyAdmin() {
        if (msg.sender != admin) revert Kernel_OnlyAdmin(msg.sender);
        _;
    }

    // ######################## ~ KERNEL INTERFACE ~ ########################

    function executeAction(Actions action_, address target_) external onlyExecutor {
        if (action_ == Actions.InstallModule) {
            ensureContract(target_);
            ensureValidKeycode(Module(target_).KEYCODE());
            _installModule(Module(target_));
        } else if (action_ == Actions.UpgradeModule) {
            ensureContract(target_);
            ensureValidKeycode(Module(target_).KEYCODE());
            _upgradeModule(Module(target_));
        } else if (action_ == Actions.ActivatePolicy) {
            ensureContract(target_);
            _activatePolicy(Policy(target_));
        } else if (action_ == Actions.DeactivatePolicy) {
            ensureContract(target_);
            _deactivatePolicy(Policy(target_));
        } else if (action_ == Actions.MigrateKernel) {
            ensureContract(target_);
            _migrateKernel(Kernel(target_));
        } else if (action_ == Actions.ChangeExecutor) {
            executor = target_;
        } else if (action_ == Actions.ChangeAdmin) {
            admin = target_;
        }

        emit ActionExecuted(action_, target_);
    }

    // ######################## ~ KERNEL INTERNAL ~ ########################

    function _installModule(Module newModule_) internal {
        Keycode keycode = newModule_.KEYCODE();

        if (address(getModuleForKeycode[keycode]) != address(0))
            revert Kernel_ModuleAlreadyInstalled(keycode);

        getModuleForKeycode[keycode] = newModule_;
        getKeycodeForModule[newModule_] = keycode;
        allKeycodes.push(keycode);

        newModule_.INIT();
    }

    function _upgradeModule(Module newModule_) internal {
        Keycode keycode = newModule_.KEYCODE();
        Module oldModule = getModuleForKeycode[keycode];

        if (address(oldModule) == address(0) || oldModule == newModule_)
            revert Kernel_InvalidModuleUpgrade(keycode);

        getKeycodeForModule[oldModule] = Keycode.wrap(bytes5(0));
        getKeycodeForModule[newModule_] = keycode;
        getModuleForKeycode[keycode] = newModule_;

        newModule_.INIT();

        _reconfigurePolicies(keycode);
    }

    function _activatePolicy(Policy policy_) internal {
        if (policy_.isActive()) revert Kernel_PolicyAlreadyApproved(address(policy_));

        // Grant permissions for policy to access restricted module functions
        Permissions[] memory requests = policy_.requestPermissions();
        _setPolicyPermissions(policy_, requests, true);

        // Add policy to list of active policies
        activePolicies.push(policy_);
        getPolicyIndex[policy_] = activePolicies.length - 1;

        // Record module dependencies
        Keycode[] memory dependencies = policy_.configureDependencies();
        uint256 depLength = dependencies.length;

        for (uint256 i; i < depLength; ) {
            Keycode keycode = dependencies[i];

            moduleDependents[keycode].push(policy_);
            getDependentIndex[keycode][policy_] = moduleDependents[keycode].length - 1;

            unchecked {
                ++i;
            }
        }

        // Set policy status to active
        policy_.setActiveStatus(true);
    }

    function _deactivatePolicy(Policy policy_) internal {
        if (!policy_.isActive()) revert Kernel_PolicyNotApproved(address(policy_));

        // Revoke permissions
        Permissions[] memory requests = policy_.requestPermissions();
        _setPolicyPermissions(policy_, requests, false);

        // Remove policy from all policy data structures
        uint256 idx = getPolicyIndex[policy_];
        Policy lastPolicy = activePolicies[activePolicies.length - 1];

        activePolicies[idx] = lastPolicy;
        activePolicies.pop();
        getPolicyIndex[lastPolicy] = idx;
        delete getPolicyIndex[policy_];

        // Remove policy from module dependents
        _pruneFromDependents(policy_);

        // Set policy status to inactive
        policy_.setActiveStatus(false);
    }

    // WARNING: ACTION WILL BRICK THIS KERNEL. All functionality will move to the new kernel
    // New kernel must add in all of the modules and policies via executeAction
    // NOTE: Data does not get cleared from this kernel
    function _migrateKernel(Kernel newKernel_) internal {
        uint256 keycodeLen = allKeycodes.length;
        for (uint256 i; i < keycodeLen; ) {
            Module module = Module(getModuleForKeycode[allKeycodes[i]]);
            module.changeKernel(newKernel_);
            unchecked {
                ++i;
            }
        }

        uint256 policiesLen = activePolicies.length;
        for (uint256 j; j < policiesLen; ) {
            Policy policy = activePolicies[j];

            // Deactivate before changing kernel
            policy.setActiveStatus(false);
            policy.changeKernel(newKernel_);
            unchecked {
                ++j;
            }
        }
    }

    function _reconfigurePolicies(Keycode keycode_) internal {
        Policy[] memory dependents = moduleDependents[keycode_];
        uint256 depLength = dependents.length;

        for (uint256 i; i < depLength; ) {
            dependents[i].configureDependencies();

            unchecked {
                ++i;
            }
        }
    }

    function _setPolicyPermissions(
        Policy policy_,
        Permissions[] memory requests_,
        bool grant_
    ) internal {
        uint256 reqLength = requests_.length;
        for (uint256 i = 0; i < reqLength; ) {
            Permissions memory request = requests_[i];
            modulePermissions[request.keycode][policy_][request.funcSelector] = grant_;

            emit PermissionsUpdated(request.keycode, policy_, request.funcSelector, grant_);

            unchecked {
                ++i;
            }
        }
    }

    function _pruneFromDependents(Policy policy_) internal {
        Keycode[] memory dependencies = policy_.configureDependencies();
        uint256 depcLength = dependencies.length;

        for (uint256 i; i < depcLength; ) {
            Keycode keycode = dependencies[i];
            Policy[] storage dependents = moduleDependents[keycode];

            uint256 origIndex = getDependentIndex[keycode][policy_];
            Policy lastPolicy = dependents[dependents.length - 1];

            // Swap with last and pop
            dependents[origIndex] = lastPolicy;
            dependents.pop();

            // Record new index and delete terminated policy index
            getDependentIndex[keycode][lastPolicy] = origIndex;
            delete getDependentIndex[keycode][policy_];

            unchecked {
                ++i;
            }
        }
    }

    function grantRole(Role role_, address addr_) public onlyAdmin {
        if (hasRole[addr_][role_]) revert Kernel_AddressAlreadyHasRole(addr_, role_);

        ensureValidRole(role_);
        if (!isRole[role_]) isRole[role_] = true;

        hasRole[addr_][role_] = true;

        emit RoleGranted(role_, addr_);
    }

    function revokeRole(Role role_, address addr_) public onlyAdmin {
        if (!isRole[role_]) revert Kernel_RoleDoesNotExist(role_);
        if (!hasRole[addr_][role_]) revert Kernel_AddressDoesNotHaveRole(addr_, role_);

        hasRole[addr_][role_] = false;

        emit RoleRevoked(role_, addr_);
    }
}

error VOTES_TransferDisabled();

contract DefaultVotes is Module, ERC20 {
    constructor(Kernel kernel_) Module(kernel_) ERC20("Voting Tokens", "VOTES", 3) {}

    function KEYCODE() public pure override returns (Keycode) {
        return Keycode.wrap("VOTES");
    }

    // Policy Interface

    function mintTo(address wallet_, uint256 amount_) external permissioned {
        _mint(wallet_, amount_);
    }

    function burnFrom(address wallet_, uint256 amount_) external permissioned {
        _burn(wallet_, amount_);
    }

    function transfer(address, uint256) public override returns (bool) {
        revert VOTES_TransferDisabled();
        return true;
    }

    function transferFrom(
        address from_,
        address to_,
        uint256 amount_
    ) public override permissioned returns (bool) {
        // skip the approve function because callers must be pre-approved via governance

        balanceOf[from_] -= amount_;
        unchecked {
            balanceOf[to_] += amount_;
        }

        emit Transfer(from_, to_, amount_);
        return true;
    }
}

// [VOTES] The Votes Module is the ERC20 token that represents voting power in the network.

error IsAlreadyReserveAsset();
error NotReserveAsset();

contract DefaultTreasury is Module {

    constructor(Kernel kernel_, ERC20[] memory initialAssets_) Module(kernel_) {
        uint256 length = initialAssets_.length;
        for (uint256 i; i < length;) {
            ERC20 asset = initialAssets_[i];
            isReserveAsset[asset] = true;
            reserveAssets.push(asset);
            unchecked {
                ++i;
            }
        }   
    }

    function KEYCODE() public pure override returns (Keycode) {
        return Keycode.wrap("TRSRY");
    }

    // VARIABLES

    mapping(ERC20 => bool) public isReserveAsset;
    ERC20[] public reserveAssets;

    // Policy Interface

    function getReserveAssets() public view returns (ERC20[] memory reserveAssets_) {
        reserveAssets_ = reserveAssets;
    }

    // whitelisting: add and remove reserve assets (if the treasury supports these currencies)

    function addReserveAsset(ERC20 asset_) public permissioned {
        if (isReserveAsset[asset_]) {revert IsAlreadyReserveAsset();}
        isReserveAsset[asset_] = true;
        reserveAssets.push(asset_);
    }

    function removeReserveAsset(ERC20 asset_) public permissioned {
        if (!isReserveAsset[asset_]) {revert NotReserveAsset();}       
        isReserveAsset[asset_] = false;
        
        uint numAssets = reserveAssets.length;
        for (uint i; i < numAssets;) {
            if (reserveAssets[i] == asset_) {
                reserveAssets[i] = reserveAssets[numAssets - 1];
                break;
            }
            unchecked {++i;}
        }
    }

    // more convenient than "transferFrom", since users only have to approve the Treasury
    // and any policy can make approved transfers on the Treasury's behalf.
    // beware of approving malicious policies that can rug the user.

    function depositFrom(address depositor_, ERC20 asset_, uint256 amount_) external permissioned {
        if (!isReserveAsset[asset_]) {revert NotReserveAsset();}
        asset_.transferFrom(depositor_, address(this), amount_);
    }

    // must withdraw assets to approved policies, where withdrawn assets are handled in their internal logic.
    // no direct withdraws to arbitrary addresses allowed.
    function withdraw(ERC20 asset_, uint256 amount_) external permissioned {
        if (!isReserveAsset[asset_]) {revert NotReserveAsset();}
        asset_.transfer(msg.sender, amount_);
    }
}

pragma solidity ^0.8.15;

interface IBond {
    
    // purchasing
    event TokensPurchased(address buyer, uint256 tokens, uint256 totalCost);
    error NotEnoughInventory();
    error ExecutionPriceTooHigh();
}

contract Bond is Policy, IBond {

    /////////////////////////////////////////////////////////////////////////////////
    //                         Kernel Policy Configuration                         //
    /////////////////////////////////////////////////////////////////////////////////

    DefaultVotes public VOTES;
    DefaultTreasury public TRSRY;

    constructor(Kernel kernel_, ERC20 DAI_) Policy(kernel_) {
        DAI = DAI_; // set the address of payment currency
    }

    function configureDependencies() external override onlyKernel returns (Keycode[] memory dependencies) {
        dependencies = new Keycode[](2);
        
        dependencies[0] = toKeycode("VOTES");
        VOTES = DefaultVotes(getModuleAddress(toKeycode("VOTES")));

        dependencies[1] = toKeycode("TRSRY");
        TRSRY = DefaultTreasury(getModuleAddress(toKeycode("TRSRY")));
    }

    function requestPermissions() external view override onlyKernel returns (Permissions[] memory requests) {
        requests = new Permissions[](2);
        requests[0] = Permissions(toKeycode("VOTES"), VOTES.mintTo.selector);
        requests[1] = Permissions(toKeycode("TRSRY"), TRSRY.depositFrom.selector);

    }

    /////////////////////////////////////////////////////////////////////////////////
    //                                Policy Variables                             //
    /////////////////////////////////////////////////////////////////////////////////

    ERC20 public DAI; // DAI contract addr

    uint256 public constant EMISSION_RATE = 25000; // tokens added to auction inventory per day
    uint256 public constant SLIPPAGE_RATE = 15; // price increase per token, denominated in 1/10,000th's of a cent (+ 15c / 10,000 tokens)
    uint256 public constant PRICE_DECAY_RATE = 187_500; // the rate that token prices decay each day, denominated in 1/10,000th's of a cent (~.19c / day)
    uint256 public constant MAX_INVENTORY = 1_000_000; // maximum number of tokens available for purchase in the auction
    uint256 public constant RESERVE_PRICE = 1_000_000; // lowest possible price for tokens to be sold in auction

    uint256 public basePrice = 1_000_000; // the base price of the auction after the last sale, priced in 1/10,000th's of a cent (starts at $1.00)
    uint256 public prevSaleTimestamp = block.timestamp; // the timestamp of the last purchase made at the bond
    
    uint256 internal prevInventory = 400_000; // the amount of tokens available for purchase in the auction (initially 400,000 PROX)

    /////////////////////////////////////////////////////////////////////////////////
    //                              View Functions                                 //
    /////////////////////////////////////////////////////////////////////////////////

    // Utility Functions.

    function _min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    function _max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    // INVENTORY

    // The auction can hold up to a maximum of 1,000,000 tokens in the inventory at a given time. 
    // The inventory "refills" over time at a rate of 25,000 tokens per day.

    function getCurrentInventory() public view returns (uint256 currentInventory) {
        // calculate the total tokens available in the auction since based on available inventory and emissions
        uint256 newEmissions = (block.timestamp - prevSaleTimestamp) * EMISSION_RATE / 1 days;

        // calculate the current inventory based on previous inventory and new emissions
        currentInventory = _min(prevInventory + newEmissions, MAX_INVENTORY);
    }

    // PRICE

    // The auction price is a factor of two variables how many tokens are purchased and 
    // time elasped since the previous sale. Each token purchased increases the price of
    // each subsequent token, and the price goes down linearly over time.

    function getTotalCost(uint256 tokensPurchased_) public view returns (uint256 totalCost, uint256 newBasePrice) {
        // price decay in cents, decays $ // maximum amount of liquidity that can be 0.25 per day ($0.01c every 3456 seconds, or ~57 minutes)
        uint256 priceDecay = (block.timestamp - prevSaleTimestamp) * PRICE_DECAY_RATE / 1 days;

        // calculate starting price of current sale based on the last recorded base price and timestamp from the previous sale
        uint256 startingPrice = basePrice > priceDecay ? _max(basePrice - priceDecay, RESERVE_PRICE) : RESERVE_PRICE;

        // final price of current sale including slippage from on tokens purchased
        uint256 finalPrice = startingPrice + (SLIPPAGE_RATE * tokensPurchased_);

        // get the average execution price
        totalCost = tokensPurchased_ * ((startingPrice + finalPrice) / 2);
        newBasePrice = finalPrice;
    }

    function purchase(uint256 tokensPurchased_, uint256 maxPrice_) external {

        uint256 currentInventory = getCurrentInventory();
        (uint256 totalCost, uint256 newBasePrice) = getTotalCost(tokensPurchased_);

        // revert the tx if there's not enough liquidity in the auction for the desired purchase amount
        if (tokensPurchased_ > currentInventory) { revert NotEnoughInventory(); }

        // revert if the execution price is worse than the minPrice_
        if (totalCost > maxPrice_ * tokensPurchased_) { revert ExecutionPriceTooHigh(); }

        // save the new inventory after purchase
        prevInventory = currentInventory - tokensPurchased_;

        // reset the purchase timestamp
        prevSaleTimestamp = block.timestamp;

        // set the new base price after purchase
        basePrice = newBasePrice;

        // transfer dai from and mint VOTES to buyer
        TRSRY.depositFrom(msg.sender, DAI, totalCost);
        VOTES.mintTo(msg.sender, tokensPurchased_);

        emit TokensPurchased(msg.sender, tokensPurchased_, totalCost);
    }
}

Contract ABI

[{"inputs":[{"internalType":"contract Kernel","name":"kernel_","type":"address"},{"internalType":"contract ERC20","name":"DAI_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ExecutionPriceTooHigh","type":"error"},{"inputs":[{"internalType":"address","name":"caller_","type":"address"}],"name":"KernelAdapter_OnlyKernel","type":"error"},{"inputs":[],"name":"NotEnoughInventory","type":"error"},{"inputs":[{"internalType":"Keycode","name":"keycode_","type":"bytes5"}],"name":"Policy_ModuleDoesNotExist","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalCost","type":"uint256"}],"name":"TokensPurchased","type":"event"},{"inputs":[],"name":"DAI","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMISSION_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_INVENTORY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRICE_DECAY_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RESERVE_PRICE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SLIPPAGE_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TRSRY","outputs":[{"internalType":"contract DefaultTreasury","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"VOTES","outputs":[{"internalType":"contract DefaultVotes","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"basePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract Kernel","name":"newKernel_","type":"address"}],"name":"changeKernel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"configureDependencies","outputs":[{"internalType":"Keycode[]","name":"dependencies","type":"bytes5[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCurrentInventory","outputs":[{"internalType":"uint256","name":"currentInventory","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokensPurchased_","type":"uint256"}],"name":"getTotalCost","outputs":[{"internalType":"uint256","name":"totalCost","type":"uint256"},{"internalType":"uint256","name":"newBasePrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kernel","outputs":[{"internalType":"contract Kernel","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"prevSaleTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokensPurchased_","type":"uint256"},{"internalType":"uint256","name":"maxPrice_","type":"uint256"}],"name":"purchase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"requestPermissions","outputs":[{"components":[{"internalType":"Keycode","name":"keycode","type":"bytes5"},{"internalType":"bytes4","name":"funcSelector","type":"bytes4"}],"internalType":"struct Permissions[]","name":"requests","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"activate_","type":"bool"}],"name":"setActiveStatus","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080604052620f42406004554260055562061a8060065534801561002257600080fd5b506040516110633803806110638339810160408190526100419161008a565b600080546001600160a01b039384166001600160a01b031991821617909155600380549290931691161790556100c4565b6001600160a01b038116811461008757600080fd5b50565b6000806040838503121561009d57600080fd5b82516100a881610072565b60208401519092506100b981610072565b809150509250929050565b610f90806100d36000396000f3fe608060405234801561001057600080fd5b50600436106101515760003560e01c80639459b875116100cd578063d4aae0c411610081578063e0bab4c411610066578063e0bab4c4146102bc578063e4b4a727146102dc578063ec7404b1146102fc57600080fd5b8063d4aae0c41461029c578063dd21d6041461027857600080fd5b8063c56d915c116100b2578063c56d915c14610282578063c733a7ba1461028b578063c7876ea41461029357600080fd5b80639459b87514610263578063b416d46e1461027857600080fd5b80634b1072d51161012457806370876c981161010957806370876c98146101e3578063765f2079146101f657806380cee4ab1461021e57600080fd5b80634b1072d5146101c65780635924be70146101ce57600080fd5b806301b8199a1461015657806322f3e2d41461017257806343ad74f3146101a75780634657b36c146101b1575b600080fd5b61015f6161a881565b6040519081526020015b60405180910390f35b6000546101979074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610169565b61015f6202dc6c81565b6101c46101bf366004610cc5565b61030f565b005b61015f600f81565b6101d66103ae565b6040516101699190610ce2565b6101c46101f1366004610d75565b61057e565b610209610204366004610d97565b610795565b60408051928352602083019190915201610169565b60025461023e9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610169565b61026b61083a565b6040516101699190610db0565b61015f620f424081565b61015f60055481565b61015f610a60565b61015f60045481565b60005461023e9073ffffffffffffffffffffffffffffffffffffffff1681565b60035461023e9073ffffffffffffffffffffffffffffffffffffffff1681565b60015461023e9073ffffffffffffffffffffffffffffffffffffffff1681565b6101c461030a366004610e16565b610aae565b60005473ffffffffffffffffffffffffffffffffffffffff163314610367576040517f14fa403c0000000000000000000000000000000000000000000000000000000081523360048201526024015b60405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005460609073ffffffffffffffffffffffffffffffffffffffff163314610404576040517f14fa403c00000000000000000000000000000000000000000000000000000000815233600482015260240161035e565b6040805160028082526060820190925290816020015b604080518082019091526000808252602082015281526020019060019003908161041a57905050905060405180604001604052806104757f564f54455300000000000000000000000000000000000000000000000000000090565b7fffffffffff0000000000000000000000000000000000000000000000000000001681527f449a52f800000000000000000000000000000000000000000000000000000000602090910152815182906000906104d3576104d3610e38565b602002602001018190525060405180604001604052806105107f545253525900000000000000000000000000000000000000000000000000000090565b7fffffffffff0000000000000000000000000000000000000000000000000000001681527f68a9674d0000000000000000000000000000000000000000000000000000000060209091015281518290600190811061057057610570610e38565b602002602001018190525090565b6000610588610a60565b905060008061059685610795565b91509150828511156105d4576040517fb77dc02500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105de8585610e96565b821115610617576040517fbc83f2dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6106218584610ed3565b6006554260055560048181556002546003546040517f68a9674d000000000000000000000000000000000000000000000000000000008152339381019390935273ffffffffffffffffffffffffffffffffffffffff90811660248401526044830185905216906368a9674d90606401600060405180830381600087803b1580156106aa57600080fd5b505af11580156106be573d6000803e3d6000fd5b50506001546040517f449a52f80000000000000000000000000000000000000000000000000000000081523360048201526024810189905273ffffffffffffffffffffffffffffffffffffffff909116925063449a52f89150604401600060405180830381600087803b15801561073457600080fd5b505af1158015610748573d6000803e3d6000fd5b505060408051338152602081018990529081018590527f8fafebcaf9d154343dad25669bfa277f4fbacd7ac6b0c4fed522580e040a0f339250606001905060405180910390a15050505050565b6000806000620151806202dc6c600554426107b09190610ed3565b6107ba9190610e96565b6107c49190610eea565b9050600081600454116107da57620f42406107f4565b6107f4826004546107eb9190610ed3565b620f4240610b4b565b9050600061080386600f610e96565b61080d9083610f25565b9050600261081b8284610f25565b6108259190610eea565b61082f9087610e96565b969095509350505050565b60005460609073ffffffffffffffffffffffffffffffffffffffff163314610890576040517f14fa403c00000000000000000000000000000000000000000000000000000000815233600482015260240161035e565b60408051600280825260608201835290916020830190803683370190505090507f564f544553000000000000000000000000000000000000000000000000000000816000815181106108e4576108e4610e38565b7fffffffffff0000000000000000000000000000000000000000000000000000009092166020928302919091019091015261094461093f7f564f54455300000000000000000000000000000000000000000000000000000090565b610b63565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff929092169190911790557f5452535259000000000000000000000000000000000000000000000000000000816001815181106109bd576109bd610e38565b7fffffffffff00000000000000000000000000000000000000000000000000000090921660209283029190910190910152610a1861093f7f545253525900000000000000000000000000000000000000000000000000000090565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905590565b600080620151806161a860055442610a789190610ed3565b610a829190610e96565b610a8c9190610eea565b9050610aa881600654610a9f9190610f25565b620f4240610c91565b91505090565b60005473ffffffffffffffffffffffffffffffffffffffff163314610b01576040517f14fa403c00000000000000000000000000000000000000000000000000000000815233600482015260240161035e565b6000805491151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff909216919091179055565b6000818311610b5a5781610b5c565b825b9392505050565b600080546040517fb4dc00b40000000000000000000000000000000000000000000000000000000081527fffffffffff00000000000000000000000000000000000000000000000000000084166004820152829173ffffffffffffffffffffffffffffffffffffffff169063b4dc00b490602401602060405180830381865afa158015610bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c189190610f3d565b905073ffffffffffffffffffffffffffffffffffffffff8116610c8b576040517f5c3fa9cd0000000000000000000000000000000000000000000000000000000081527fffffffffff0000000000000000000000000000000000000000000000000000008416600482015260240161035e565b92915050565b6000818310610b5a5781610b5c565b73ffffffffffffffffffffffffffffffffffffffff81168114610cc257600080fd5b50565b600060208284031215610cd757600080fd5b8135610b5c81610ca0565b602080825282518282018190526000919060409081850190868401855b82811015610d6857815180517fffffffffff0000000000000000000000000000000000000000000000000000001685528601517fffffffff0000000000000000000000000000000000000000000000000000000016868501529284019290850190600101610cff565b5091979650505050505050565b60008060408385031215610d8857600080fd5b50508035926020909101359150565b600060208284031215610da957600080fd5b5035919050565b6020808252825182820181905260009190848201906040850190845b81811015610e0a5783517fffffffffff0000000000000000000000000000000000000000000000000000001683529284019291840191600101610dcc565b50909695505050505050565b600060208284031215610e2857600080fd5b81358015158114610b5c57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615610ece57610ece610e67565b500290565b600082821015610ee557610ee5610e67565b500390565b600082610f20577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008219821115610f3857610f38610e67565b500190565b600060208284031215610f4f57600080fd5b8151610b5c81610ca056fea2646970667358221220177aa7b6812d34853696fcb3a02736e8afc6cf89b2a9b17e600b56c0cb0b1b4164736f6c634300080f0033000000000000000000000000ad961758441a99147478c594d70868c1104eb071000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000ad961758441a99147478c594d70868c1104eb071000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1

-----Decoded View---------------
Arg [0] : kernel_ (address): 0xad961758441a99147478c594d70868c1104eb071
Arg [1] : DAI_ (address): 0xda10009cbd5d07dd0cecc66161fc93d7c9000da1

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000ad961758441a99147478c594d70868c1104eb071
Arg [1] : 000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1


Deployed ByteCode Sourcemap

25857:6100:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27404:45;;27444:5;27404:45;;;;;160:25:1;;;148:2;133:18;27404:45:0;;;;;;;;11020:20;;;;;;;;;;;;;;;361:14:1;;354:22;336:41;;324:2;309:18;11020:20:0;196:187:1;27641:50:0;;27684:7;27641:50;;9833:99;;;;;;:::i;:::-;;:::i;:::-;;27501:42;;27541:2;27501:42;;26768:319;;;:::i;:::-;;;;;;;:::i;30846:1108::-;;;;;;:::i;:::-;;:::i;29905:933::-;;;;;;:::i;:::-;;:::i;:::-;;;;2387:25:1;;;2443:2;2428:18;;2421:34;;;;2360:18;29905:933:0;2213:248:1;26192:28:0;;;;;;;;;;;;2666:42:1;2654:55;;;2636:74;;2624:2;2609:18;26192:28:0;2466:250:1;26361:399:0;;;:::i;:::-;;;;;;;:::i;27796:49::-;;27836:9;27796:49;;28182:50;;;;;;29158:466;;;:::i;28034:36::-;;;;;;9594:20;;;;;;;;;27358:16;;;;;;;;;26160:25;;;;;;;;;11889:100;;;;;;:::i;:::-;;:::i;9833:99::-;9753:6;;;;9731:10;:29;9727:78;;9769:36;;;;;9794:10;9769:36;;;2636:74:1;2609:18;;9769:36:0;;;;;;;;9727:78;9905:6:::1;:19:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;9833:99::o;26768:319::-;9753:6;;26841:29;;9753:6;;9731:10;:29;9727:78;;9769:36;;;;;9794:10;9769:36;;;2636:74:1;2609:18;;9769:36:0;2466:250:1;9727:78:0;26894:20:::1;::::0;;26912:1:::1;26894:20:::0;;;;;::::1;::::0;;;;::::1;;;;-1:-1:-1::0;;;;;;;;;;;;;;;;;26894:20:0::1;;;;;;;;;;;;;;;26883:31;;26939:54;;;;;;;;26951:18;;7058:8:::0;6972:99;26951:18:::1;26939:54:::0;::::1;::::0;;26971:21;26939:54:::1;::::0;;::::1;::::0;26925:11;;:8;;-1:-1:-1;;26925:11:0::1;;;;:::i;:::-;;;;;;:68;;;;27018:59;;;;;;;;27030:18;;7058:8:::0;6972:99;27030:18:::1;27018:59:::0;::::1;::::0;;27050:26;27018:59:::1;::::0;;::::1;::::0;27004:11;;:8;;27013:1:::1;::::0;27004:11;::::1;;;;;:::i;:::-;;;;;;:73;;;;26768:319:::0;:::o;30846:1108::-;30931:24;30958:21;:19;:21::i;:::-;30931:48;;30991:17;31010:20;31034:30;31047:16;31034:12;:30::i;:::-;30990:74;;;;31205:16;31186;:35;31182:73;;;31232:20;;;;;;;;;;;;;;31182:73;31353:28;31365:16;31353:9;:28;:::i;:::-;31341:9;:40;31337:81;;;31392:23;;;;;;;;;;;;;;31337:81;31496:35;31515:16;31496;:35;:::i;:::-;31480:13;:51;31605:15;31585:17;:35;31683:9;:24;;;-1:-1:-1;31774:5:0;31804:3;;31774:45;;;;;31792:10;31774:45;;;5914:34:1;;;;31774:5:0;31804:3;;;5964:18:1;;;5957:43;6016:18;;;6009:34;;;31774:5:0;;:17;;5826:18:1;;31774:45:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;31830:5:0;;:42;;;;;31843:10;31830:42;;;6228:74:1;6318:18;;;6311:34;;;31830:5:0;;;;;-1:-1:-1;31830:12:0;;-1:-1:-1;6201:18:1;;31830:42:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;31890:56:0;;;31906:10;6558:74:1;;6663:2;6648:18;;6641:34;;;6691:18;;;6684:34;;;31890:56:0;;-1:-1:-1;6546:2:1;6531:18;;-1:-1:-1;31890:56:0;;;;;;;30918:1036;;;30846:1108;;:::o;29905:933::-;29974:17;29993:20;30169:18;30249:6;27684:7;30209:17;;30191:15;:35;;;;:::i;:::-;30190:56;;;;:::i;:::-;:65;;;;:::i;:::-;30169:86;;30396:21;30432:10;30420:9;;:22;:84;;27958:9;30420:84;;;30445:43;30462:10;30450:9;;:22;;;;:::i;:::-;27958:9;30445:4;:43::i;:::-;30396:108;-1:-1:-1;30601:18:0;30639:32;30655:16;27541:2;30639:32;:::i;:::-;30622:50;;:13;:50;:::i;:::-;30601:71;-1:-1:-1;30792:1:0;30762:26;30601:71;30762:13;:26;:::i;:::-;30761:32;;;;:::i;:::-;30741:53;;:16;:53;:::i;:::-;30729:65;30820:10;;-1:-1:-1;29905:933:0;-1:-1:-1;;;;29905:933:0:o;26361:399::-;9753:6;;26432:29;;9753:6;;9731:10;:29;9727:78;;9769:36;;;;;9794:10;9769:36;;;2636:74:1;2609:18;;9769:36:0;2466:250:1;9727:78:0;26489:16:::1;::::0;;26503:1:::1;26489:16:::0;;;;;::::1;::::0;;;;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;-1:-1:-1;;26474:31:0;-1:-1:-1;26544:18:0::1;26526:12;26539:1;26526:15;;;;;;;;:::i;:::-;:36:::0;;;::::1;:15;::::0;;::::1;::::0;;;;;;;:36;26594::::1;26611:18;;7058:8:::0;6972:99;26611:18:::1;26594:16;:36::i;:::-;26573:5;:58:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;26662:18:::1;26644:12;26657:1;26644:15;;;;;;;;:::i;:::-;:36:::0;;;::::1;:15;::::0;;::::1;::::0;;;;;;;:36;26715::::1;26732:18;;7058:8:::0;6972:99;26715:36:::1;26691:5;:61:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;26361:399;:::o;29158:466::-;29210:24;29360:20;29439:6;27444:5;29402:17;;29384:15;:35;;;;:::i;:::-;29383:53;;;;:::i;:::-;:62;;;;:::i;:::-;29360:85;;29567:49;29588:12;29572:13;;:28;;;;:::i;:::-;27836:9;29567:4;:49::i;:::-;29548:68;;29236:388;29158:466;:::o;11889:100::-;9753:6;;;;9731:10;:29;9727:78;;9769:36;;;;;9794:10;9769:36;;;2636:74:1;2609:18;;9769:36:0;2466:250:1;9727:78:0;11961:8:::1;:20:::0;;;::::1;;::::0;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;11889:100::o;28843:107::-;28902:7;28933:1;28929;:5;:13;;28941:1;28929:13;;;28937:1;28929:13;28922:20;28843:107;-1:-1:-1;;;28843:107:0:o;11521:290::-;11588:7;11643:6;;:36;;;;;7343:66:1;7331:79;;11643:36:0;;;7313:98:1;11588:7:0;;11643:6;;;:26;;7286:18:1;;11643:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11608:72;-1:-1:-1;11695:30:0;;;11691:78;;11734:35;;;;;7343:66:1;7331:79;;11734:35:0;;;7313:98:1;7286:18;;11734:35:0;7141:276:1;11691:78:0;11787:16;11521:290;-1:-1:-1;;11521:290:0:o;28728:107::-;28787:7;28818:1;28814;:5;:13;;28826:1;28814:13;;388:162:1;482:42;475:5;471:54;464:5;461:65;451:93;;540:1;537;530:12;451:93;388:162;:::o;555:270::-;629:6;682:2;670:9;661:7;657:23;653:32;650:52;;;698:1;695;688:12;650:52;737:9;724:23;756:39;789:5;756:39;:::i;830:940::-;1057:2;1109:21;;;1179:13;;1082:18;;;1201:22;;;1028:4;;1057:2;1242;;1260:18;;;;1301:15;;;1028:4;1344:400;1358:6;1355:1;1352:13;1344:400;;;1417:13;;1459:9;;1470:66;1455:82;1443:95;;1582:11;;1576:18;1596:66;1572:91;1558:12;;;1551:113;1684:12;;;;1719:15;;;;1380:1;1373:9;1344:400;;;-1:-1:-1;1761:3:1;;830:940;-1:-1:-1;;;;;;;830:940:1:o;1775:248::-;1843:6;1851;1904:2;1892:9;1883:7;1879:23;1875:32;1872:52;;;1920:1;1917;1910:12;1872:52;-1:-1:-1;;1943:23:1;;;2013:2;1998:18;;;1985:32;;-1:-1:-1;1775:248:1:o;2028:180::-;2087:6;2140:2;2128:9;2119:7;2115:23;2111:32;2108:52;;;2156:1;2153;2146:12;2108:52;-1:-1:-1;2179:23:1;;2028:180;-1:-1:-1;2028:180:1:o;2721:731::-;2918:2;2970:21;;;3040:13;;2943:18;;;3062:22;;;2889:4;;2918:2;3141:15;;;;3115:2;3100:18;;;2889:4;3184:242;3198:6;3195:1;3192:13;3184:242;;;3263:13;;3278:66;3259:86;3247:99;;3401:15;;;;3366:12;;;;3220:1;3213:9;3184:242;;;-1:-1:-1;3443:3:1;;2721:731;-1:-1:-1;;;;;;2721:731:1:o;4199:273::-;4255:6;4308:2;4296:9;4287:7;4283:23;4279:32;4276:52;;;4324:1;4321;4314:12;4276:52;4363:9;4350:23;4416:5;4409:13;4402:21;4395:5;4392:32;4382:60;;4438:1;4435;4428:12;4897:184;4949:77;4946:1;4939:88;5046:4;5043:1;5036:15;5070:4;5067:1;5060:15;5086:184;5138:77;5135:1;5128:88;5235:4;5232:1;5225:15;5259:4;5256:1;5249:15;5275:228;5315:7;5441:1;5373:66;5369:74;5366:1;5363:81;5358:1;5351:9;5344:17;5340:105;5337:131;;;5448:18;;:::i;:::-;-1:-1:-1;5488:9:1;;5275:228::o;5508:125::-;5548:4;5576:1;5573;5570:8;5567:34;;;5581:18;;:::i;:::-;-1:-1:-1;5618:9:1;;5508:125::o;6729:274::-;6769:1;6795;6785:189;;6830:77;6827:1;6820:88;6931:4;6928:1;6921:15;6959:4;6956:1;6949:15;6785:189;-1:-1:-1;6988:9:1;;6729:274::o;7008:128::-;7048:3;7079:1;7075:6;7072:1;7069:13;7066:39;;;7085:18;;:::i;:::-;-1:-1:-1;7121:9:1;;7008:128::o;7422:273::-;7506:6;7559:2;7547:9;7538:7;7534:23;7530:32;7527:52;;;7575:1;7572;7565:12;7527:52;7607:9;7601:16;7626:39;7659:5;7626:39;:::i

Metadata Hash

177aa7b6812d34853696fcb3a02736e8afc6cf89b2a9b17e600b56c0cb0b1b41
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.