Code Monkey home page Code Monkey logo

contractreview-seaport-conduitcontroller.sol's Introduction

Seaport

Seaport is a marketplace contract for safely and efficiently creating and fulfilling orders for ERC721 and ERC1155 items. Each order contains an arbitrary number of items that the offerer is willing to give (the "offer") along with an arbitrary number of items that must be received along with their respective receivers (the "consideration").

One could say seaport is a generalizied ETH/ERC20/ERC721/ERC1155 marketplace.

Conduit Controller

ConduitController enables deploying and managing new conduits, or contracts that allow registered callers (or open "channels") to transfer approved ERC20/721/1155 tokens on their behalf.

1. pragma solidity ^0.8.7;

specifies the compiler version that should be used

4. import {
5.   ConduitControllerInterface
6. } from "../interfaces/ConduitControllerInterface.sol";

ConduitControllerInterface.sol contains all external functions, interfaces, struct, events and errors for the ConduitController.sol. The ConduitController.sol uses a struct form the ConduitControllerInterface.sol and this struct tracks the current key, current owner, new potential owner and open channels for each deployed conduit.

8. import { ConduitInterface } from "../interfaces/ConduitInterface.sol";

ConduitInterface.sol contains all external function interfaces, events and error for conduit contracts. The NewConduit event which takes an address and a bytes32(conduit,conduitkey) was emitted in the ConduitController.sol

10. import { Conduit } from "./Conduit.sol";

The Conduit.sol serves as an originator for "proxied" transfers. Each conduit is deployed and controlled by the ConduitController.sol that can add and remove "channels" or contracts that can instruct the Conduit.sol to transfer approve ERC20/721/1155 tokens.

21. mapping(address => ConduitProperties) internal _conduits;

The above is a mapping of addresses to a struct registering keys, owners, new potential owners and channels by conduit

24. bytes32 internal immutable _CONDUIT_CREATION_CODE_HASH;

The above code sets the hash of the conduit creation code as an immutable argument.

25. bytes32 internal immutable _CONDUIT_RUNTIME_CODE_HASH;

The above code sets the hash of the runtime code as an immutable argument.

31. constructor() {

This constructor initialize the contract by deploying a conduit and setting the creation code and runtime code hashes as immutable arguments.

33. _CONDUIT_CREATION_CODE_HASH = keccak256(type(Conduit).creationCode);

This derive the conduit creation code hash and sets it as an immutable.

36. Conduit zzeroConduit = new Conduit{ salt: bytes32(0) }();

This deploys a conduit with the zero hash as the salt.

39. _CONDUIT_RUNTIME_CODE_HASH = address(zeroConduit). codehash;
40. }

This retrieve the conduit runtime code hash and set it as an immutable.

41. function createConduit(bytes32 conduitKey, address initialOwner)
        external
        override
        returns(address conduit)
    {

This function deploys a new conduit using a supplied conduit key and assigning an initial owner for the deployed conduit. The parameter conduitkey it used to deploy the conduit. The parameter initialOwner is the initial owner to set for the new conduit. This function returns the address of the newly deployed conduit.

62. if (initialOwner == address(0)) {
63.            revert InvalidInitialOwner();
64.        }

An if statement to ensure that an initail owner has been supplied.

67. if (address(uint160(bytes20(conduitKey))) != msg.sender) {
69.                revert InvalidCreator();
70.        }

This if statement ensures that if the first 20 bytes of the conduit key do not match the caller it reverts with an error indicating that the creator is invalid.

 73. conduit = address(
 74.           uint160(
 75.               uint256(
 76.                   keccak256(
 77.                       abi.encodePacked(
 78.                           bytes1(0xff),
 79.                           address(this),
 80.                           conduitKey,
 81.                           _CONDUIT_CREATION_CODE_HASH
 82.                       )
 83.                   )
 84.               )
 85.           )
 86.       );

This derives address from deployer, conduit key and creation code hash.

89. if (conduit.codehash == _CONDUIT_RUNTIME_CODE_HASH) {
91. revert ConduitAlreadyExists(conduit);
92.        }

Here if derived conduit exists, aas evidenced by comparing runtime code this should revert with an error indicating that the conduit already exists.

95.  new Conduit{ salt: conduitKey }();

The code above deploys the conduit via CREAT2 using the conduit key as the salt.

98. ConduitProperties storage conduitProperties = _conduits[conduit];

This initialize storage variable referencing conduit properties.

101. conduitProperties.owner = initialOwner;

This set the supplied initial owner as the owner of the conduit.

104. conduitProperties.key = conduitKey;

This sets conduit key used to deploy the conduit to enable reverse lookup.

107. emit NewConduit(conduit, conduitKey);

Emit an event indicating that the conduit has been deployed.

 110. emit OwnershipTransferred(conduit, address(0), initialOwner);
    }

Emit an event indicating that conduit ownership has been assigned.

 125. function updateChannel(
 126.       address conduit,
 127.       address channel,
 128.       bool isOpen
 129.   ) external override {

This function opens or closes a channel on a given conduit, therby allowing the specified account to execute transfers against that conduit. Only the owner of the conduit in question may call this function. The parameter conduit signifies the conduit for which to open or close the channel. This parameter channel signifies the channel to open or close on the conduit. this parameter isOpen takes in a boolean indicating whether to open or close the channel.

131. _assertCallerIsConduitOwner(conduit);
This ensures that the caller is the current owner of the conduit in question.
``` solidity
134. ConduitInterface(conduit).updateChannel(channel, isOpen);

This calls the conduit, updating the channel.

137. ConduitProperties storage conduitProperties = _conduits[conduit];

Retrieve storage region where channels for the conduit are tracked.

140. uint256 channelIndexPlusOne = (
141.            conduitProperties.channelIndexesPlusOne[channel]
142.        );

Retrieve the index, if one currently exists, for the updated channel.

145. bool channelPreviouslyOpen = channelIndexPlusOne != 0;

This determines whether the updated channel is already tracked as open.

148. if (isOpen && !channelPreviouslyOpen) {

An if statement to check that channels has been set to pen and was previously closed

150. conduitProperties.channels.push(channel);

This adds the channel to the channels array for the conduit.

153. conduitProperties.channelIndexesPlusOne[channel] = (
154.                conduitProperties.channels.length
155.            );
156.        } else if (!isOpen && channelPreviouslyOpen) {

The codes on lines 153-156 adds new open channel length to associated mapping as index + 1.

uint256 removedChannelIndex;

This decrements located index to get the index of the closed channel.

163. unchecked {
164.                removedChannelIndex = channelIndexPlusOne - 1;
165.            }

This Skips underflow check as channelPreviouslyOpen being true ensures that channelIndexPlusOne is not zero.

168. uint256 finalChannelIndex = conduitProperties.channels.length - 1;

This uses the length of channels array to determine index of last channel.

171. if (finalChannelIndex != removedChannelIndex) {
173. address finalChannel = 
(
174.                    conduitProperties.channels[finalChannelIndex]
175.               );

This ensures that if closed channel is not last channel in the channels array the final channel and place the value on the stack is retrieved

conduitProperties.channels[removedChannelIndex] = finalChannel;

This overwrites the removed channel using the final channel value.

181. conduitProperties.channelIndexesPlusOne[finalChannel] = (
182.                    channelIndexPlusOne
183.                );
184.           }

Updates the final index in associated mapping to removed index.

conduitProperties.channels.pop();

Remove the last channel from the channels array for the conduit.

delete conduitProperties.channelIndexesPlusOne[channel];
       }
   }

this removes the colsed channel from the asociated mapping of indexes.

   
    function transferOwnership(address conduit, address newPotentialOwner)
        external
        override
    {

The function above is responsible for initiating conduit ownership transfer by assigning a new potential owner for the given conduit. Once set, the new potential owner may call acceptOwnership to claim ownership of the conduit. Only the owner of the conduit in question may call this function. The parameter conduit stands for the conduit for which to initiate ownership transfer. The parameter newPotentialOwner stands for the new potential owner of the conduit.

 _assertCallerIsConduitOwner(conduit);

This line of code ensures the caller is the current owner of the conduit in question.

if (newPotentialOwner == address(0)) {
            revert NewPotentialOwnerIsZeroAddress(conduit);
        }

The above code ensures the new potential owner is not an invalid address.

 if (newPotentialOwner == _conduits[conduit].potentialOwner) {
            revert NewPotentialOwnerAlreadySet(conduit, newPotentialOwner);
        }

This ensures the new potential owner is not already set.

 emit PotentialOwnerUpdated(newPotentialOwner);

Here an event is emited indicating that the potential owner has been updated.

   _conduits[conduit].potentialOwner = newPotentialOwner;
    }

This sets the new potential owner as the potential owner of the conduit.

 function cancelOwnershipTransfer(address conduit) external override {

This function clears the currently set potential owner, if any, from a conduit. This can only be done by the owner of the conduit in questestion The parameter conduit The conduit for which to cancel ownership transfer.

        _assertCallerIsConduitOwner(conduit);

Here its ensured that the caller of this function is the current owner of the conduit in question.

        if (_conduits[conduit].potentialOwner == address(0)) {
            revert NoPotentialOwnerCurrentlySet(conduit);
        }

The above line of code ensures that ownership transfer is currently possible.

 emit PotentialOwnerUpdated(address(0));

The above line emits an event indicating that the potential owner has been cleared.

  _conduits[conduit].potentialOwner = address(0);
    }

This Clears the current new potential owner from the conduit.

    function acceptOwnership(address conduit) external override {

This function accepts ownership of a supplied conduit. Only accounts that the current owner has set as the new potential owner may call this function. The prameter conduit signifies the conduit for which to accept ownership.

_assertConduitExists(conduit);

This ensures that the conduit in question exists.

        if (msg.sender != _conduits[conduit].potentialOwner) {
           revert CallerIsNotNewPotentialOwner(conduit);
        }

This checks if caller does not match current potential owner of the conduit, it reverts indicating that caller is not current potential owner.

    emit PotentialOwnerUpdated(address(0));

This emits an event indicating that the potential owner has been cleared.

        _conduits[conduit].potentialOwner = address(0);

This clears the current new potential owner from the conduit.

emit OwnershipTransferred(
            conduit,
            _conduits[conduit].owner,
            msg.sender
        );

This emits an event indicating conduit ownership has been transferred.

        _conduits[conduit].owner = msg.sender;
    }

This sets the caller as the owner of the conduit.

function ownerOf(address conduit)
        external
        view
        override
        returns (address owner)
    {

This function retrieves the current owner of a deployed conduit return owner the owner of the supplied conduit.

The paramerter conduit The conduit for which to retrieve the associated owner.

        _assertConduitExists(conduit);

This ensures that the conduit in question exists.

owner = _conduits[conduit].owner;
    }

This retrieves the current owner of the conduit in question.

 function getKey(address conduit)
        external
        view
        override
        returns (bytes32 conduitKey)
    {

This function retrieves the conduit key for a deployed conduit via reverse lookup, and it returns conduitKey used to deploy the supplied conduit. This parameter conduit The conduit for which to retrieve the associated conduit key.

        conduitKey = _conduits[conduit].key;

The above line of code attempts to retrieve a conduit key for the conduit in question.

if (conduitKey == bytes32(0)) {
            revert NoConduit();
        }
    }

The above if statement reverts if no conduit key was located.

 function getConduit(bytes32 conduitKey)
        external
        view
        override
        returns (address conduit, bool exists)
    {

The function above derives the conduit associated with a given conduit key and determine whether that conduit exists (i.e. whether it has been deployed) this function returns conduit which signifies the address derived from the coduit it also returns exist which is a boolean indicating whether the derived conduit has been deployed or not. The parameter conduitKey is the conduit key used to derive the conduit.

 conduit = address(
            uint160(
                uint256(
                    keccak256(
                        abi.encodePacked(
                            bytes1(0xff),
                            address(this),
                            conduitKey,
                            _CONDUIT_CREATION_CODE_HASH
                        )
                    )
                )
            )
        );

The above line of code derive address from deployer, conduit key and creation code hash.

exists = (conduit.codehash == _CONDUIT_RUNTIME_CODE_HASH);
    }

Determine whether conduit exists by retrieving its runtime code.

 function getPotentialOwner(address conduit)
        external
        view
        override
        returns (address potentialOwner)
    {

This function retrieves the potential owner, if any, for a given conduit. The current owner may set a new potential owner viatransferOwnership and that owner may then accept ownership of the conduit in question via acceptOwnership and it returns the potential owner, if any, for the conduit. The conduit parameter signifies the conduit for which to retrieve the potential owner.

        _assertConduitExists(conduit);

Ensures that the conduit in question exists.

 potentialOwner = _conduits[conduit].potentialOwner;
    }

Retrieves the current potential owner of the conduit in question.

   function getChannelStatus(address conduit, address channel)
        external
        view
        override
        returns (bool isOpen)
    {       

This function retrieves the status (either open or closed) of a given channel on a conduit and it returns the status of thr channel on the given conduit. The parameter conduit signifies the conduit for which to retrieve the channel status. The parameter channel signifies the channel for which to retrieve the status.

 _assertConduitExists(conduit);

Ensures that the conduit in question exists.

  isOpen = _conduits[conduit].channelIndexesPlusOne[channel] != 0;
    }

Retrieves the current channel status for the conduit in question.

 function getTotalChannels(address conduit)
        external
        view
        override
        returns (uint256 totalChannels)
    {

This function retrieves the total number of open channels for a given conduit, it returns the total number of open channels for the conduit. Here the conduit parameter signifies the conduit for which to retrieve the total channel count.

        _assertConduitExists(conduit);

Ensures that the conduit in question exists.

totalChannels = _conduits[conduit].channels.length;
    }

Retrieves the total open channel count for the conduit in question.

 function getChannel(address conduit, uint256 channelIndex)
        external
        view
        override
        returns (address channel)
    {

The functoin above retrieves an open channel at a specific index for a given conduit and returns the open channel, if any, at the specified channel index.

       _assertConduitExists(conduit);

Ensures that the conduit in question exists.

        uint256 totalChannels = _conduits[conduit].channels.length;

Retrieves the total open channel count for the conduit in question.

if (channelIndex >= totalChannels) {
            revert ChannelOutOfRange(conduit);
        }

Ensures that the supplied index is within range.

channel = _conduits[conduit].channels[channelIndex];
    }

Retrieves the channel at the given index.

function getChannels(address conduit)
        external
        view
        override
        returns (address[] memory channels)
    {

The function above retrieves all open channels for a given conduit. Note that calling this function for a conduit with many channels will revert with an out-of-gas error it returns an array of open channels on the given conduit. The parameter conduit signifies the conduit for which to retrieve open channels.

        _assertConduitExists(conduit);

Ensures that the conduit in question exists.

 channels = _conduits[conduit].channels;
    }

Retrieves all of the open channels on the conduit in question.

function getConduitCodeHashes()
        external
        view
        override
        returns (bytes32 creationCodeHash, bytes32 runtimeCodeHash)
    {

A function that retrieves the conduit creation code and runtime code hashes.

        creationCodeHash = _CONDUIT_CREATION_CODE_HASH;

Retrieves the conduit creation code hash from runtime.

  runtimeCodeHash = _CONDUIT_RUNTIME_CODE_HASH;
    }

Retrieves the conduit runtime code hash from runtime.

    function _assertCallerIsConduitOwner(address conduit) private view {

Above is a private view function to revert if the caller is not the owner of a given conduit. The parameter conduit signifies the conduit for which to assert ownership.

        _assertConduitExists(conduit);

Ensures that the conduit in question exists.

        if (msg.sender != _conduits[conduit].owner) {

If the caller does not match the current owner of the conduit...

revert CallerIsNotOwner(conduit);
        }
    }

Revert, indicating that the caller is not the owner.

    function _assertConduitExists(address conduit) private view {

A private view function to revert if a given conduit does not exist.

        if (_conduits[conduit].key == bytes32(0)) {

Attempts to retrieve a conduit key for the conduit in question.

revert NoConduit();
        }
    }
    
}    

Reverts if no conduit key was located.

contractreview-seaport-conduitcontroller.sol's People

Contributors

immanuelolivia1 avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.