ETH Price: $2,105.71 (-2.89%)

Contract Diff Checker

Contract Name:
Settlement

Contract Source Code:

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)

pragma solidity ^0.8.0;

import "./Ownable.sol";

/**
 * @dev Contract module which provides access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership} and {acceptOwnership}.
 *
 * This module is used through inheritance. It will make available all functions
 * from parent (Ownable).
 */
abstract contract Ownable2Step is Ownable {
    address private _pendingOwner;

    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Returns the address of the pending owner.
     */
    function pendingOwner() public view virtual returns (address) {
        return _pendingOwner;
    }

    /**
     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual override onlyOwner {
        _pendingOwner = newOwner;
        emit OwnershipTransferStarted(owner(), newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual override {
        delete _pendingOwner;
        super._transferOwnership(newOwner);
    }

    /**
     * @dev The new owner accepts the ownership transfer.
     */
    function acceptOwnership() public virtual {
        address sender = _msgSender();
        require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner");
        _transferOwnership(sender);
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor() {
        _paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        require(!paused(), "Pausable: paused");
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        require(paused(), "Pausable: not paused");
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

/**
 * Copyright 2024 Circle Internet Financial, LTD. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.8.16;

/**
 * @title ILiquiditySource
 */
interface ILiquiditySource {
    /**
     * @notice Emitted when liquidity is supplied to a recipient.
     */
    event LiquiditySupplied(address indexed recipient, uint256 amount);

    /**
     * @notice Supplies liquidity to a recipient
     * @param recipient Receiver of liquidity
     * @param amount Amount of liquidity to transfer
     */
    function supplyTo(address recipient, uint256 amount) external;

    /**
     * @notice The available liquidity that can be supplied
     * @return The available liquidity amount
     */
    function availableLiquidity() external view returns (uint256);
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

/**
 * Copyright 2024 Circle Internet Financial, LTD. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.8.16;

/**
 * @title IRedemption
 */
interface IRedemption {
    /**
     * @notice The asset being redeemed.
     * @return The address of the asset token.
     */
    function asset() external view returns (address);

    /**
     * @notice The liquidity token that the asset is being redeemed for.
     * @return The address of the liquidity token.
     */
    function liquidity() external view returns (address);

    /**
     * @notice Redeems an amount of asset for liquidity
     * @param amount The amount of the asset token to redeem
     */
    function redeem(uint256 amount) external;
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

/**
 * Copyright 2024 Circle Internet Financial, LTD. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.8.16;

/**
 * @title ISettlement
 */
interface ISettlement {
    /**
     * @notice The recipient of the redemption swap: where the asset gets transferred to.
     * @return The address of the recipient.
     */
    function recipient() external view returns (address);

    /**
     * @notice The liquidity available for settlement.
     * @return The amount of liquidity available
     */
    function availableLiquidity() external view returns (uint256);

    /**
     * @notice Settles the redemption request, by transferring liquidity to the redeemer.
     */
    function redeem(address redeemer, uint256 amount) external;
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

/**
 * Copyright 2024 Circle Internet Financial, LTD. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.8.16;

import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol";
import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";

/**
 * @title OwnablePausable
 * @notice Combines the Ownable2Step and Pausable types.
 * @dev Owner can rotate the Pauser role.
 */
contract OwnablePausable is Ownable2Step, Pausable {
    /**
     * @notice Emitted when the pauser address changes
     * @param oldPauser Prior pauser address
     * @param newPauser Updated pauser address
     */
    event PauserUpdated(address indexed oldPauser, address indexed newPauser);

    /**
     * @notice Address currently set as pauser
     */
    address public pauser;

    /**
     * @notice Checks that the sender is the pauser
     */
    modifier onlyPauser() {
        require(msg.sender == pauser, "Caller not pauser");
        _;
    }

    /**
     * @dev Owner and pauser addresses are explicitly passed.
     */
    constructor(address _owner, address _pauser) {
        _transferOwnership(_owner);
        pauser = _pauser;
    }

    /**
     * @notice Sets a new Pauser.
     * @dev Only callable by the Owner.
     */
    function updatePauser(address newPauser) external onlyOwner {
        require(
            newPauser != address(0),
            "Pausable: new pauser is the zero address"
        );
        emit PauserUpdated(pauser, newPauser);
        pauser = newPauser;
    }

    /**
     * @dev Only callable by the Pauser.
     */
    function pause() external onlyPauser {
        _pause();
    }

    /**
     * @dev Only callable by the Pauser.
     */
    function unpause() external onlyPauser {
        _unpause();
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

/**
 * Copyright 2024 Circle Internet Financial, LTD. All rights reserved.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.8.16;

import {ISettlement} from "./interfaces/ISettlement.sol";
import {IRedemption} from "./interfaces/IRedemption.sol";
import {ILiquiditySource} from "./interfaces/ILiquiditySource.sol";
import {OwnablePausable} from "./roles/OwnablePausable.sol";

/**
 * @title Settlement
 * @dev Pausable by the Pauser
 */
contract Settlement is ISettlement, OwnablePausable {
    /**
     * @notice Emitted when the current recipient address changes
     * @param oldRecipient Prior recipient address
     * @param newRecipient Updated recipient address
     */
    event RecipientUpdated(
        address indexed oldRecipient,
        address indexed newRecipient
    );

    /**
     * @notice Emitted when the current liquidity source changes
     * @param oldSource Prior source address
     * @param newSource Updated source address
     */
    event LiquiditySourceUpdated(
        address indexed oldSource,
        address indexed newSource
    );

    /**
     * @notice Emitted when settlement is completed.
     * @param redeemer Initiator of redemption transaction
     * @param amount the amount being redeemed, 1:1 with liquidity
     */
    event SettlementCompleted(address indexed redeemer, uint256 amount);

    /**
     * @notice Immutable redemption contract
     */
    IRedemption public immutable redemption;

    /**
     * @notice Current liquidity source
     */
    ILiquiditySource public liquiditySource;

    /**
     * @inheritdoc ISettlement
     */
    address public recipient;

    /**
     * @param _redemption Address of the redemption contract
     * @param _recipient Address that receives the asset
     * @param _owner Owner address, capable of changing the pauser
     * and adjusting parameters.
     * @param _pauser Address of pauser
     */
    constructor(
        address _redemption,
        address _recipient,
        address _owner,
        address _pauser
    ) OwnablePausable(_owner, _pauser) {
        redemption = IRedemption(_redemption);
        recipient = _recipient;
    }

    /**
     * @inheritdoc ISettlement
     * @dev Only callable when not paused.
     * @dev Only callable by the redemption contract
     */
    function redeem(
        address redeemer,
        uint256 amount
    ) external override whenNotPaused {
        require(
            msg.sender == address(redemption),
            "Settlement: caller not redemption"
        );

        require(
            address(liquiditySource) != address(0),
            "Settlement: no liquidity source set"
        );

        require(
            liquiditySource.availableLiquidity() >= amount,
            "Settlement: exceeds allowed amount"
        );

        liquiditySource.supplyTo(redeemer, amount);
        emit SettlementCompleted(redeemer, amount);
    }

    /**
     * @inheritdoc ISettlement
     * @dev Delegates to the currently set liquidity source.
     */
    function availableLiquidity() external view override returns (uint256) {
        if (address(liquiditySource) == address(0)) {
            return 0;
        }
        return liquiditySource.availableLiquidity();
    }

    /**
     * @notice Updates the recipient.
     * @dev Only callable by the owner.
     * @dev Allows setting to the 0 address.
     */
    function updateRecipient(address _recipient) external onlyOwner {
        emit RecipientUpdated(recipient, _recipient);
        recipient = _recipient;
    }

    /**
     * @notice Updates the current liquidity source.
     * @dev Only callable by the owner.
     * @dev Allows setting to the 0 address.
     */
    function updateLiquiditySource(
        address _liquiditySource
    ) external onlyOwner {
        emit LiquiditySourceUpdated(address(liquiditySource), _liquiditySource);
        liquiditySource = ILiquiditySource(_liquiditySource);
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):