Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x2CE8144d92ebDAB9753f6802fc81095A89B8c77E
Balance 0 ETH
Nonce 96
Code Size 3414 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

3414 bytes
0x6080604081815260048036101561001557600080fd5b600092833560e01c9081630fce3415146105fd57508063224242ca1461053c5780633bee58f9146104f45780634fce7a2a146104af57806365c4ce7a1461047657806365fae35e1461042d5780639954b0dc1461037c5780639c52a7f114610322578063bb34534c146102e2578063bf353dbb1461029e578063c72ea280146100e65763f29c29c4146100a757600080fd5b346100e25760206003193601126100e2573573ffffffffffffffffffffffffffffffffffffffff811681036100e2576100df906109f9565b51f35b8280fd5b5091903461029a578060031936011261029a578235906024803567ffffffffffffffff81116102965736602382011215610296578086013561012781610723565b91610134855193846106e2565b8183523684838301011161029257818792856020930183860137830101523385526002602052828520541561028257831561025a578051156102325761017984610c0d565b3b610204576101889084610b6b565b9590156101d857505073ffffffffffffffffffffffffffffffffffffffff6020941691829151937f0cd38bafbc8c2cb5072315a7b539e28d90c3292776c056f5d92231cf92b94920339186a48152f35b838351917fc07e79d4000000000000000000000000000000000000000000000000000000008352820152fd5b5093925051917f96b2aadb000000000000000000000000000000000000000000000000000000008352820152fd5b8583517f665adf1d000000000000000000000000000000000000000000000000000000008152fd5b8583517f08a6c2e5000000000000000000000000000000000000000000000000000000008152fd5b5063d957b595845233602052601cfd5b8680fd5b8480fd5b5080fd5b50346100e25760206003193601126100e2573573ffffffffffffffffffffffffffffffffffffffff81168091036100e2578282916020945280845220549051908152f35b50913461031f57602060031936011261031f575073ffffffffffffffffffffffffffffffffffffffff61031760209335610c0d565b915191168152f35b80fd5b50346100e25760206003193601126100e2573573ffffffffffffffffffffffffffffffffffffffff811681036100e25733835282602052818320541561036b576100df906108c6565b634a0bfec18352336020526024601cfd5b82843461031f578060031936011261031f57600361039a815461093a565b9082835b835181101561041957806103b46103ea926107c3565b905473ffffffffffffffffffffffffffffffffffffffff91861b1c811687526002602052878720546001146103ef575b50610989565b61039e565b6103f8826107c3565b905490861b1c1661041261040b85610989565b94876109e5565b52876103e4565b8184528551806104298682610646565b0390f35b50346100e25760206003193601126100e2573573ffffffffffffffffffffffffffffffffffffffff811681036100e25733835282602052818320541561036b576100df906107fa565b50346100e25760206003193601126100e2573573ffffffffffffffffffffffffffffffffffffffff811681036100e2576100df90610ab5565b50346100e25760206003193601126100e2573573ffffffffffffffffffffffffffffffffffffffff81168091036100e257828291602094526002845220549051908152f35b50346100e25760206003193601126100e2573573ffffffffffffffffffffffffffffffffffffffff81168091036100e257818360019260209552600285522054149051908152f35b82843461031f578060031936011261031f5760019161055b835461093a565b918080855b610578575b5050610429935082525191829182610646565b84518110156105f857906105c782610590889461075d565b73ffffffffffffffffffffffffffffffffffffffff809254600392831b1c168552846020528588862054146105ce575b5050610989565b9091610560565b6105d78361075d565b9054911b1c166105f06105e987610989565b96896109e5565b5288806105c0565b610565565b9291905034610642576020600319360112610642573573ffffffffffffffffffffffffffffffffffffffff811680910361064257835260208381529220546001148152f35b8380fd5b6020908160408183019282815285518094520193019160005b82811061066d575050505090565b835173ffffffffffffffffffffffffffffffffffffffff168552938101939281019260010161065f565b6040810190811067ffffffffffffffff8211176106b357604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176106b357604052565b67ffffffffffffffff81116106b357601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b6001548110156107945760016000527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6003548110156107945760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0190600090565b73ffffffffffffffffffffffffffffffffffffffff809116906000908282528160205260016040832054146108c15760016040832055600154680100000000000000008110156108945761085581600186930160015561075d565b909283549160031b90811b9283911b169119161790557fe31c10b0adbedd0c6e5d024286c6eeead7761e65a67608dcf0b67604c0da7e2f3391604051a3565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b505050565b73ffffffffffffffffffffffffffffffffffffffff1660008181528060205260408120541561091e578060408120557f58466e5837b54e559819c9ba8a5d7c77c97c985d1aabf4bdc5f41069fa5d65a03391604051a3565b5050565b67ffffffffffffffff81116106b35760051b60200190565b9061094482610922565b61095160405191826106e2565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061097f8294610922565b0190602036910137565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146109b65760010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80518210156107945760209160051b010190565b600033815280602052604081205415610aa45773ffffffffffffffffffffffffffffffffffffffff80921691828252600260205260016040832054146108c157600160408320556003546801000000000000000081101561089457610a658160018693016003556107c3565b909283549160031b90811b9283911b169119161790557f75d30ca40c7bcd48e685894b82b864808b9cb566090efc53444a2e61742f18a33391604051a3565b634a0bfec19052336020526024601cfd5b60009033825281602052604082205415610b215773ffffffffffffffffffffffffffffffffffffffff1690818152600260205260408120541561091e578060408120557fdadd1471db1ea2f303654fb1bdcc010e5a664214ab41934c0f752aabca88a4913391604051a3565b634a0bfec18252336020526024601cfd5b60405190610b3f82610697565b601082527f67363d3d37363d34f03d5260086018f3000000000000000000000000000000006020830152565b9190610b75610b32565b9083825160206000940184f59373ffffffffffffffffffffffffffffffffffffffff851615610c04578291610baa8392610c0d565b9582602083519301915af13d15610bff573d610bc581610723565b90610bd360405192836106e2565b81528260203d92013e5b158015610bf6575b610bf0575060019190565b91508190565b50823b15610be5565b610bdd565b50508092509190565b610c15610b32565b602081519101206040519060208201927fff0000000000000000000000000000000000000000000000000000000000000084523060601b602184015260358301526055820152605581526080810181811067ffffffffffffffff8211176106b3577f010000000000000000000000000000000000000000000000000000000000000060b673ffffffffffffffffffffffffffffffffffffffff948360405284519020937fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060a08201957fd694000000000000000000000000000000000000000000000000000000000000875260601b1660a2820152015260178152610d1981610697565b519020169056fea264697066735822122017729a378b65b9b3351906a8b9b6851850b732e41cdbd98d9cfe264cf72ee42964736f6c63430008100033

Verified Source Code Full Match

Compiler: v0.8.16+commit.07a7930e EVM: london Optimization: Yes (10000 runs)
Greenhouse.sol 71 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import {Auth} from "chronicle-std/auth/Auth.sol";
import {Toll} from "chronicle-std/toll/Toll.sol";

import {IGreenhouse} from "./IGreenhouse.sol";

import {LibCREATE3} from "./libs/LibCREATE3.sol";

/**
 * @title Greenhouse
 * @custom:version 1.0.0
 *
 * @notice A greenhouse to plant contracts using CREATE3
 *
 * @dev Greenhouse is a contract factory planting contracts at deterministic
 *      addresses. The address of the planted contract solely depends on the
 *      provided salt.
 *
 *      The contract uses `chronicle-std`'s `Auth` module to grant addresses
 *      access to protected functions. `chronicle-std`'s `Toll` module is
 *      utilized to determine which addresses are eligible to plant new
 *      contracts. Note that auth'ed addresses are _not_ eligible to plant new
 *      contracts.
 */
contract Greenhouse is IGreenhouse, Auth, Toll {
    constructor(address initialAuthed) Auth(initialAuthed) {}

    /// @inheritdoc IGreenhouse
    ///
    /// @custom:invariant Planted contract's address is deterministic and solely
    ///                   depends on `salt`.
    ///                     ∀s ∊ bytes32: plant(s, _) = addressOf(s)
    function plant(bytes32 salt, bytes memory creationCode)
        external
        toll
        returns (address)
    {
        if (salt == bytes32(0)) {
            revert EmptySalt();
        }
        if (creationCode.length == 0) {
            revert EmptyCreationCode();
        }

        if (addressOf(salt).code.length != 0) {
            revert AlreadyPlanted(salt);
        }

        bool ok;
        address addr;
        (ok, addr) = LibCREATE3.tryDeploy(salt, creationCode);
        if (!ok) {
            revert PlantingFailed(salt);
        }
        // assert(addr == addressOf(salt));

        emit Planted(msg.sender, salt, addr);

        return addr;
    }

    /// @inheritdoc IGreenhouse
    function addressOf(bytes32 salt) public view returns (address) {
        return LibCREATE3.addressOf(salt);
    }

    /// @dev Defines authorization for IToll's authenticated functions.
    function toll_auth() internal override(Toll) auth {}
}
IGreenhouse.sol 69 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

interface IGreenhouse {
    /// @notice Thrown if salt `salt` already planted.
    /// @param salt The salt to plant.
    error AlreadyPlanted(bytes32 salt);

    /// @notice Thrown if planting at salt `salt` failed.
    /// @param salt The salt to plant.
    error PlantingFailed(bytes32 salt);

    /// @notice Thrown if provided salt is empty.
    error EmptySalt();

    /// @notice Thrown if provided creation code is empty.
    error EmptyCreationCode();

    /// @notice Emitted when new contract planted.
    /// @param caller The caller's address.
    /// @param salt The salt the contract got planted at.
    /// @param addr The address of the planted contract.
    event Planted(
        address indexed caller, bytes32 indexed salt, address indexed addr
    );

    /// @notice Plants a new contract with creation code `creationCode` to a
    ///         deterministic address solely depending on the salt `salt`.
    ///
    /// @dev Only callable by toll'ed addresses.
    ///
    /// @dev Note to add constructor arguments to the creation code, if
    ///      applicable!
    ///
    /// @custom:example Appending constructor arguments to the creation code:
    ///
    ///     ```solidity
    ///     bytes memory creationCode = abi.encodePacked(
    ///         // Receive the creation code of `MyContract`.
    ///         type(MyContract).creationCode,
    ///
    ///         // `MyContract` receives as constructor arguments an address
    ///         // and a uint.
    ///         abi.encode(address(0xcafe), uint(1))
    ///     );
    ///     ```
    ///
    /// @param salt The salt to plant the contract at.
    /// @param creationCode The creation code of the contract to plant.
    /// @return The address of the planted contract.
    function plant(bytes32 salt, bytes memory creationCode)
        external
        returns (address);

    /// @notice Returns the deterministic address for salt `salt`.
    /// @dev Note that the address is not guaranteed to be utilized yet.
    ///
    /// @custom:example Verifying a contract is planted at some salt:
    ///
    ///     ```solidity
    ///     bytes32 salt = bytes32("salt");
    ///     address contract_ = addressOf(salt);
    ///     bool isPlanted = contract_.code.length != 0;
    ///     ```
    ///
    /// @param salt The salt to query their deterministic address.
    /// @return The deterministic address for given salt.
    function addressOf(bytes32 salt) external view returns (address);
}
LibCREATE3.sol 125 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

/**
 * @title LibCREATE3
 *
 * @notice Library to deploy to deterministic addresses without an initcode
 *         factor
 *
 * @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/CREATE3.sol)
 * @author Modified from Solady (https://github.com/Vectorized/solady/blob/50cbe1909e773b7e4ba76049c75a203e626d55ba/src/utils/CREATE3.sol)
 */
library LibCREATE3 {
    // ╭────────────────────────────────────────────────────────────────────╮
    // │ Opcode      │ Mnemonic         │ Stack        │ Memory             │
    // ├────────────────────────────────────────────────────────────────────┤
    // │ 36          │ CALLDATASIZE     │ cds          │                    │
    // │ 3d          │ RETURNDATASIZE   │ 0 cds        │                    │
    // │ 3d          │ RETURNDATASIZE   │ 0 0 cds      │                    │
    // │ 37          │ CALLDATACOPY     │              │ [0..cds): calldata │
    // │ 36          │ CALLDATASIZE     │ cds          │ [0..cds): calldata │
    // │ 3d          │ RETURNDATASIZE   │ 0 cds        │ [0..cds): calldata │
    // │ 34          │ CALLVALUE        │ value 0 cds  │ [0..cds): calldata │
    // │ f0          │ CREATE           │ newContract  │ [0..cds): calldata │
    // ├────────────────────────────────────────────────────────────────────┤
    // │ Opcode      │ Mnemonic         │ Stack        │ Memory             │
    // ├────────────────────────────────────────────────────────────────────┤
    // │ 67 bytecode │ PUSH8 bytecode   │ bytecode     │                    │
    // │ 3d          │ RETURNDATASIZE   │ 0 bytecode   │                    │
    // │ 52          │ MSTORE           │              │ [0..8): bytecode   │
    // │ 60 0x08     │ PUSH1 0x08       │ 0x08         │ [0..8): bytecode   │
    // │ 60 0x18     │ PUSH1 0x18       │ 0x18 0x08    │ [0..8): bytecode   │
    // │ f3          │ RETURN           │              │ [0..8): bytecode   │
    // ╰────────────────────────────────────────────────────────────────────╯
    bytes private constant _PROXY_BYTECODE =
        hex"67363d3d37363d34f03d5260086018f3";

    bytes32 private constant _PROXY_BYTECODE_HASH = keccak256(_PROXY_BYTECODE);

    /// @dev Deploys `creationCode` deterministically with `salt` and returns the
    ///      deployed contract's address.
    ///
    ///      Note that the address of the deployed contract solely depends on
    ///      `salt`. The deterministic address for `salt` can be computed
    ///      beforehand via `addressOf(bytes32)(address)`.
    function tryDeploy(bytes32 salt, bytes memory creationCode)
        internal
        returns (bool, address)
    {
        // Load proxy's bytecode into memory as direct access not supported in
        // inline assembly.
        bytes memory proxyBytecode = _PROXY_BYTECODE;

        address proxy;
        assembly ("memory-safe") {
            // Deploy a new contract with pre-made bytecode via CREATE2.
            // Start 32 bytes into the code to avoid copying the byte length.
            // forgefmt: disable-next-item
            proxy := create2(
                        0,
                        add(proxyBytecode, 32),
                        mload(proxyBytecode),
                        salt
                     )
        }

        // Fail if deployment failed.
        if (proxy == address(0)) {
            return (false, address(0));
        }

        // Get deployed proxy and initialize creationCode.
        address deployed = addressOf(salt);
        (bool ok,) = proxy.call(creationCode);

        // Fail if call or initialization failed.
        if (!ok || deployed.code.length == 0) {
            return (false, address(0));
        }

        // Otherwise return deployed contract address.
        return (true, deployed);
    }

    /// @dev Returns the deterministic address for `salt`.
    function addressOf(bytes32 salt) internal view returns (address) {
        address proxy = address(
            uint160(
                uint(
                    keccak256(
                        abi.encodePacked(
                            // Prefix:
                            bytes1(0xFF),
                            // Creator:
                            address(this),
                            // Salt:
                            salt,
                            // Bytecode hash:
                            _PROXY_BYTECODE_HASH
                        )
                    )
                )
            )
        );

        return address(
            uint160(
                uint(
                    keccak256(
                        abi.encodePacked(
                            // 0xd6 =   0xc0 (short RLP prefix)
                            //        + 0x16 (length of 0x94 ++ proxy ++ 0x01)
                            // 0x94 =   0x80
                            //        + 0x14 (0x14 = 20 = length of address)
                            hex"d694",
                            proxy,
                            // Nonce of proxy contract:
                            hex"01"
                        )
                    )
                )
            )
        );
    }
}
Auth.sol 124 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import {IAuth} from "./IAuth.sol";

/**
 * @title Auth Module
 *
 * @dev The `Auth` contract module provides a basic access control mechanism,
 *      where a set of addresses are granted access to protected functions.
 *      These addresses are said to be _auth'ed_.
 *
 *      Initially, the address given as constructor argument is the only address
 *      auth'ed. Through the `rely(address)` and `deny(address)` functions,
 *      auth'ed callers are able to grant/renounce auth to/from addresses.
 *
 *      This module is used through inheritance. It will make available the
 *      modifier `auth`, which can be applied to functions to restrict their
 *      use to only auth'ed callers.
 */
abstract contract Auth is IAuth {
    /// @dev Mapping storing whether address is auth'ed.
    /// @custom:invariant Image of mapping is {0, 1}.
    ///                     ∀x ∊ Address: _wards[x] ∊ {0, 1}
    /// @custom:invariant Only address given as constructor argument is authenticated after deployment.
    ///                     deploy(initialAuthed) → (∀x ∊ Address: _wards[x] == 1 → x == initialAuthed)
    /// @custom:invariant Only functions `rely` and `deny` may mutate the mapping's state.
    ///                     ∀x ∊ Address: preTx(_wards[x]) != postTx(_wards[x])
    ///                                     → (msg.sig == "rely" ∨ msg.sig == "deny")
    /// @custom:invariant Mapping's state may only be mutated by authenticated caller.
    ///                     ∀x ∊ Address: preTx(_wards[x]) != postTx(_wards[x]) → _wards[msg.sender] = 1
    mapping(address => uint) private _wards;

    /// @dev List of addresses possibly being auth'ed.
    /// @dev May contain duplicates.
    /// @dev May contain addresses not being auth'ed anymore.
    /// @custom:invariant Every address being auth'ed once is element of the list.
    ///                     ∀x ∊ Address: authed(x) -> x ∊ _wardsTouched
    address[] private _wardsTouched;

    /// @dev Ensures caller is auth'ed.
    modifier auth() {
        assembly ("memory-safe") {
            // Compute slot of _wards[msg.sender].
            mstore(0x00, caller())
            mstore(0x20, _wards.slot)
            let slot := keccak256(0x00, 0x40)

            // Revert if caller not auth'ed.
            let isAuthed := sload(slot)
            if iszero(isAuthed) {
                // Store selector of `NotAuthorized(address)`.
                mstore(0x00, 0x4a0bfec1)
                // Store msg.sender.
                mstore(0x20, caller())
                // Revert with (offset, size).
                revert(0x1c, 0x24)
            }
        }
        _;
    }

    constructor(address initialAuthed) {
        _wards[initialAuthed] = 1;
        _wardsTouched.push(initialAuthed);

        // Note to use address(0) as caller to indicate address was auth'ed
        // during deployment.
        emit AuthGranted(address(0), initialAuthed);
    }

    /// @inheritdoc IAuth
    function rely(address who) external auth {
        if (_wards[who] == 1) return;

        _wards[who] = 1;
        _wardsTouched.push(who);
        emit AuthGranted(msg.sender, who);
    }

    /// @inheritdoc IAuth
    function deny(address who) external auth {
        if (_wards[who] == 0) return;

        _wards[who] = 0;
        emit AuthRenounced(msg.sender, who);
    }

    /// @inheritdoc IAuth
    function authed(address who) public view returns (bool) {
        return _wards[who] == 1;
    }

    /// @inheritdoc IAuth
    /// @custom:invariant Only contains auth'ed addresses.
    ///                     ∀x ∊ authed(): _wards[x] == 1
    /// @custom:invariant Contains all auth'ed addresses.
    ///                     ∀x ∊ Address: _wards[x] == 1 → x ∊ authed()
    function authed() public view returns (address[] memory) {
        // Initiate array with upper limit length.
        address[] memory wardsList = new address[](_wardsTouched.length);

        // Iterate through all possible auth'ed addresses.
        uint ctr;
        for (uint i; i < wardsList.length; i++) {
            // Add address only if still auth'ed.
            if (_wards[_wardsTouched[i]] == 1) {
                wardsList[ctr++] = _wardsTouched[i];
            }
        }

        // Set length of array to number of auth'ed addresses actually included.
        assembly ("memory-safe") {
            mstore(wardsList, ctr)
        }

        return wardsList;
    }

    /// @inheritdoc IAuth
    function wards(address who) public view returns (uint) {
        return _wards[who];
    }
}
Toll.sol 125 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

import {IToll} from "./IToll.sol";

/**
 * @title Toll Module
 *
 * @notice "Toll paid, we kiss - but dissension looms, maybe diss?"
 *
 * @dev The `Toll` contract module provides a basic access control mechanism,
 *      where a set of addresses are granted access to protected functions.
 *      These addresses are said the be _tolled_.
 *
 *      Initially, no address is tolled. Through the `kiss(address)` and
 *      `diss(address)` functions, auth'ed callers are able to toll/de-toll
 *      addresses. Authentication for these functions is defined via the
 *      downstream implemented `toll_auth()` function.
 *
 *      This module is used through inheritance. It will make available the
 *      modifier `toll`, which can be applied to functions to restrict their
 *      use to only tolled callers.
 */
abstract contract Toll is IToll {
    /// @dev Mapping storing whether address is tolled.
    /// @custom:invariant Image of mapping is {0, 1}.
    ///                     ∀x ∊ Address: _buds[x] ∊ {0, 1}
    /// @custom:invariant Only functions `kiss` and `diss` may mutate the mapping's state.
    ///                     ∀x ∊ Address: preTx(_buds[x]) != postTx(_buds[x])
    ///                                     → (msg.sig == "kiss" ∨ msg.sig == "diss")
    /// @custom:invariant Mapping's state may only be mutated by authenticated caller.
    ///                     ∀x ∊ Address: preTx(_buds[x]) != postTx(_buds[x])
    ///                                     → toll_auth()
    mapping(address => uint) private _buds;

    /// @dev List of addresses possibly being tolled.
    /// @dev May contain duplicates.
    /// @dev May contain addresses not being tolled anymore.
    /// @custom:invariant Every address being tolled once is element of the list.
    ///                     ∀x ∊ Address: tolled(x) → x ∊ _budsTouched
    address[] private _budsTouched;

    /// @dev Ensures caller is tolled.
    modifier toll() {
        assembly ("memory-safe") {
            // Compute slot of _buds[msg.sender].
            mstore(0x00, caller())
            mstore(0x20, _buds.slot)
            let slot := keccak256(0x00, 0x40)

            // Revert if caller not tolled.
            let isTolled := sload(slot)
            if iszero(isTolled) {
                // Store selector of `NotTolled(address)`.
                mstore(0x00, 0xd957b595)
                // Store msg.sender.
                mstore(0x20, caller())
                // Revert with (offset, size).
                revert(0x1c, 0x24)
            }
        }
        _;
    }

    /// @dev Reverts if caller not allowed to access protected function.
    /// @dev Must be implemented in downstream contract.
    function toll_auth() internal virtual;

    /// @inheritdoc IToll
    function kiss(address who) external {
        toll_auth();

        if (_buds[who] == 1) return;

        _buds[who] = 1;
        _budsTouched.push(who);
        emit TollGranted(msg.sender, who);
    }

    /// @inheritdoc IToll
    function diss(address who) external {
        toll_auth();

        if (_buds[who] == 0) return;

        _buds[who] = 0;
        emit TollRenounced(msg.sender, who);
    }

    /// @inheritdoc IToll
    function tolled(address who) public view returns (bool) {
        return _buds[who] == 1;
    }

    /// @inheritdoc IToll
    /// @custom:invariant Only contains tolled addresses.
    ///                     ∀x ∊ tolled(): _tolled[x]
    /// @custom:invariant Contains all tolled addresses.
    ///                     ∀x ∊ Address: _tolled[x] == 1 → x ∊ tolled()
    function tolled() public view returns (address[] memory) {
        // Initiate array with upper limit length.
        address[] memory budsList = new address[](_budsTouched.length);

        // Iterate through all possible tolled addresses.
        uint ctr;
        for (uint i; i < budsList.length; i++) {
            // Add address only if still tolled.
            if (_buds[_budsTouched[i]] == 1) {
                budsList[ctr++] = _budsTouched[i];
            }
        }

        // Set length of array to number of tolled addresses actually included.
        assembly ("memory-safe") {
            mstore(budsList, ctr)
        }

        return budsList;
    }

    /// @inheritdoc IToll
    function bud(address who) public view returns (uint) {
        return _buds[who];
    }
}
IAuth.sol 44 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

interface IAuth {
    /// @notice Thrown by protected function if caller not auth'ed.
    /// @param caller The caller's address.
    error NotAuthorized(address caller);

    /// @notice Emitted when auth granted to address.
    /// @param caller The caller's address.
    /// @param who The address auth got granted to.
    event AuthGranted(address indexed caller, address indexed who);

    /// @notice Emitted when auth renounced from address.
    /// @param caller The caller's address.
    /// @param who The address auth got renounced from.
    event AuthRenounced(address indexed caller, address indexed who);

    /// @notice Grants address `who` auth.
    /// @dev Only callable by auth'ed address.
    /// @param who The address to grant auth.
    function rely(address who) external;

    /// @notice Renounces address `who`'s auth.
    /// @dev Only callable by auth'ed address.
    /// @param who The address to renounce auth.
    function deny(address who) external;

    /// @notice Returns whether address `who` is auth'ed.
    /// @param who The address to check.
    /// @return True if `who` is auth'ed, false otherwise.
    function authed(address who) external view returns (bool);

    /// @notice Returns full list of addresses granted auth.
    /// @dev May contain duplicates.
    /// @return List of addresses granted auth.
    function authed() external view returns (address[] memory);

    /// @notice Returns whether address `who` is auth'ed.
    /// @custom:deprecated Use `authed(address)(bool)` instead.
    /// @param who The address to check.
    /// @return 1 if `who` is auth'ed, 0 otherwise.
    function wards(address who) external view returns (uint);
}
IToll.sol 44 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

interface IToll {
    /// @notice Thrown by protected function if caller not tolled.
    /// @param caller The caller's address.
    error NotTolled(address caller);

    /// @notice Emitted when toll granted to address.
    /// @param caller The caller's address.
    /// @param who The address toll got granted to.
    event TollGranted(address indexed caller, address indexed who);

    /// @notice Emitted when toll renounced from address.
    /// @param caller The caller's address.
    /// @param who The address toll got renounced from.
    event TollRenounced(address indexed caller, address indexed who);

    /// @notice Grants address `who` toll.
    /// @dev Only callable by auth'ed address.
    /// @param who The address to grant toll.
    function kiss(address who) external;

    /// @notice Renounces address `who`'s toll.
    /// @dev Only callable by auth'ed address.
    /// @param who The address to renounce toll.
    function diss(address who) external;

    /// @notice Returns whether address `who` is tolled.
    /// @param who The address to check.
    /// @return True if `who` is tolled, false otherwise.
    function tolled(address who) external view returns (bool);

    /// @notice Returns full list of addresses tolled.
    /// @dev May contain duplicates.
    /// @return List of addresses tolled.
    function tolled() external view returns (address[] memory);

    /// @notice Returns whether address `who` is tolled.
    /// @custom:deprecated Use `tolled(address)(bool)` instead.
    /// @param who The address to check.
    /// @return 1 if `who` is tolled, 0 otherwise.
    function bud(address who) external view returns (uint);
}

Read Contract

addressOf 0xbb34534c → address
authed 0x0fce3415 → bool
authed 0x224242ca → address[]
bud 0x4fce7a2a → uint256
tolled 0x3bee58f9 → bool
tolled 0x9954b0dc → address[]
wards 0xbf353dbb → uint256

Write Contract 5 functions

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

deny 0x9c52a7f1
address who
diss 0x65c4ce7a
address who
kiss 0xf29c29c4
address who
plant 0xc72ea280
bytes32 salt
bytes creationCode
returns: address
rely 0x65fae35e
address who

Recent Transactions

No transactions found for this address