Actions

SimpleWriteAccessController Verification: Difference between revisions

From Chainlink Community Wiki

(Created page with "This page provides specific instructions on how to verify a deployed <code>SimpleWriteAccessController.sol</code> contract on etherscan. This enables you to view and manage the contract via etherscan's web UI. == '''Verifying A SimpleWriteAccessController''' == The instructions in this example will contain an example Access Controller contract on Rinkeby, but the directions will be equally applicable to any network that uses an etherscan-based explorer. https://rinkeb...")
 
No edit summary
 
(2 intermediate revisions by the same user not shown)
Line 31: Line 31:
Once on the next page, be sure to open the drop-down for "'''Optimization'''" and set it to Yes.
Once on the next page, be sure to open the drop-down for "'''Optimization'''" and set it to Yes.


The <code>SimpleWriteAccessController.sol</code> source code is available in the [https://raw.githubusercontent.com/smartcontractkit/chainlink/develop/contracts/src/v0.8/SimpleWriteAccessController.sol Chainlink Github repo.].
The <code>SimpleWriteAccessController.sol</code> source code is available in the drop down below:
<div class="toccolours mw-collapsible mw-collapsed">
'''SimpleWriteAccessController Source Code''' (Expand option is to the right --->)
<div class="mw-collapsible-content"><pre style="white-space:pre-wrap; width:100%; border:1px solid lightgrey; background:black; color:white;">// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
 
interface OwnableInterface {
  function owner() external returns (address);
 
  function transferOwnership(address recipient) external;
 
  function acceptOwnership() external;
}
 
/**
* @title The ConfirmedOwner contract
* @notice A contract with helpers for basic contract ownership.
*/
contract ConfirmedOwnerWithProposal is OwnableInterface {
  address private s_owner;
  address private s_pendingOwner;
 
  event OwnershipTransferRequested(address indexed from, address indexed to);
  event OwnershipTransferred(address indexed from, address indexed to);
 
  constructor(address newOwner, address pendingOwner) {
    require(newOwner != address(0), "Cannot set owner to zero");
 
    s_owner = newOwner;
    if (pendingOwner != address(0)) {
      _transferOwnership(pendingOwner);
    }
  }
 
  /**
  * @notice Allows an owner to begin transferring ownership to a new address,
  * pending.
  */
  function transferOwnership(address to) public override onlyOwner {
    _transferOwnership(to);
  }
 
  /**
  * @notice Allows an ownership transfer to be completed by the recipient.
  */
  function acceptOwnership() external override {
    require(msg.sender == s_pendingOwner, "Must be proposed owner");
 
    address oldOwner = s_owner;
    s_owner = msg.sender;
    s_pendingOwner = address(0);
 
    emit OwnershipTransferred(oldOwner, msg.sender);
  }
 
  /**
  * @notice Get the current owner
  */
  function owner() public view override returns (address) {
    return s_owner;
  }
 
  /**
  * @notice validate, transfer ownership, and emit relevant events
  */
  function _transferOwnership(address to) private {
    require(to != msg.sender, "Cannot transfer to self");
 
    s_pendingOwner = to;
 
    emit OwnershipTransferRequested(s_owner, to);
  }
 
  /**
  * @notice validate access
  */
  function _validateOwnership() internal view {
    require(msg.sender == s_owner, "Only callable by owner");
  }
 
  /**
  * @notice Reverts if called by anyone other than the contract owner.
  */
  modifier onlyOwner() {
    _validateOwnership();
    _;
  }
}
 
/**
* @title The ConfirmedOwner contract
* @notice A contract with helpers for basic contract ownership.
*/
contract ConfirmedOwner is ConfirmedOwnerWithProposal {
  constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}
}
 
interface AccessControllerInterface {
  function hasAccess(address user, bytes calldata data) external view returns (bool);
}
 
/**
* @title SimpleWriteAccessController
* @notice Gives access to accounts explicitly added to an access list by the
* controller's owner.
* @dev does not make any special permissions for externally, see
* SimpleReadAccessController for that.
*/
contract SimpleWriteAccessController is AccessControllerInterface, ConfirmedOwner {
  bool public checkEnabled;
  mapping(address => bool) internal accessList;
 
  event AddedAccess(address user);
  event RemovedAccess(address user);
  event CheckAccessEnabled();
  event CheckAccessDisabled();
 
  constructor() ConfirmedOwner(msg.sender) {
    checkEnabled = true;
  }
 
  /**
  * @notice Returns the access of an address
  * @param _user The address to query
  */
  function hasAccess(address _user, bytes memory) public view virtual override returns (bool) {
    return accessList[_user] || !checkEnabled;
  }
 
  /**
  * @notice Adds an address to the access list
  * @param _user The address to add
  */
  function addAccess(address _user) external onlyOwner {
    if (!accessList[_user]) {
      accessList[_user] = true;
 
      emit AddedAccess(_user);
    }
  }
 
  /**
  * @notice Removes an address from the access list
  * @param _user The address to remove
  */
  function removeAccess(address _user) external onlyOwner {
    if (accessList[_user]) {
      accessList[_user] = false;
 
      emit RemovedAccess(_user);
    }
  }
 
  /**
  * @notice makes the access check enforced
  */
  function enableAccessCheck() external onlyOwner {
    if (!checkEnabled) {
      checkEnabled = true;
 
      emit CheckAccessEnabled();
    }
  }
 
  /**
  * @notice makes the access check unenforced
  */
  function disableAccessCheck() external onlyOwner {
    if (checkEnabled) {
      checkEnabled = false;
 
      emit CheckAccessDisabled();
    }
  }
 
  /**
  * @dev reverts if the caller does not have access
  */
  modifier checkAccess() {
    require(hasAccess(msg.sender, msg.data), "No access");
    _;
  }
}</pre></div>
</div>
 


Copy the contents on that page and paste it into the empty field titled "'''Enter the Solidity Contract Code below'''"
Copy the contents on that page and paste it into the empty field titled "'''Enter the Solidity Contract Code below'''"
----


=== '''Copy in the Constructor Arguments''' ===
=== '''Copy in the Constructor Arguments''' ===
The Constructor Arguments are available below:
You do not need to provide the constructor arguments for the <code>SimpleWriteAccessController</code> contract, since we did not set any values when deploying the contract.
----


=== '''Set Miscellaneous Settings''' ===
=== '''Set Miscellaneous Settings''' ===
Line 42: Line 228:


Leave the other options as their defaults.
Leave the other options as their defaults.
Once you have the above completed, click the button to verify the contract.

Latest revision as of 19:50, 30 May 2022

This page provides specific instructions on how to verify a deployed SimpleWriteAccessController.sol contract on etherscan.

This enables you to view and manage the contract via etherscan's web UI.

Verifying A SimpleWriteAccessController

The instructions in this example will contain an example Access Controller contract on Rinkeby, but the directions will be equally applicable to any network that uses an etherscan-based explorer.

https://rinkeby.etherscan.io/address/0x30f3e33D93C79572642B89C631Df3D180dd965Bf#code


Set Base Variables for Verifying the Contract

Navigate the your deployed contract's address in Etherscan, then click on the Contract tab.

If the contract is not verified, then you will see a page with the contract's ByteCode and an option to "Verify and Publish" the contract.

EtherscanUnverifiedSimpleWriteAccessControllerContract.png

We'll go ahead and click on "Verify and Publish", which takes us to a new page.

Here we will want to confirm the contract's address, set the compiler type to Solidity (Single file), and then set the Compiler Version to 0.8.0+commit.c7dfd78e.

Lastly, since Chainlink uses the MIT License (MIT), we'll want to select that as well.

Then click "Continue"

EtherscanUnverifiedSimpleWriteAccessControllerSetVarsForVerification.png


Copy Over the Source Code of the Contract

Once on the next page, be sure to open the drop-down for "Optimization" and set it to Yes.

The SimpleWriteAccessController.sol source code is available in the drop down below:

SimpleWriteAccessController Source Code (Expand option is to the right --->)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface OwnableInterface {
  function owner() external returns (address);

  function transferOwnership(address recipient) external;

  function acceptOwnership() external;
}

/**
 * @title The ConfirmedOwner contract
 * @notice A contract with helpers for basic contract ownership.
 */
contract ConfirmedOwnerWithProposal is OwnableInterface {
  address private s_owner;
  address private s_pendingOwner;

  event OwnershipTransferRequested(address indexed from, address indexed to);
  event OwnershipTransferred(address indexed from, address indexed to);

  constructor(address newOwner, address pendingOwner) {
    require(newOwner != address(0), "Cannot set owner to zero");

    s_owner = newOwner;
    if (pendingOwner != address(0)) {
      _transferOwnership(pendingOwner);
    }
  }

  /**
   * @notice Allows an owner to begin transferring ownership to a new address,
   * pending.
   */
  function transferOwnership(address to) public override onlyOwner {
    _transferOwnership(to);
  }

  /**
   * @notice Allows an ownership transfer to be completed by the recipient.
   */
  function acceptOwnership() external override {
    require(msg.sender == s_pendingOwner, "Must be proposed owner");

    address oldOwner = s_owner;
    s_owner = msg.sender;
    s_pendingOwner = address(0);

    emit OwnershipTransferred(oldOwner, msg.sender);
  }

  /**
   * @notice Get the current owner
   */
  function owner() public view override returns (address) {
    return s_owner;
  }

  /**
   * @notice validate, transfer ownership, and emit relevant events
   */
  function _transferOwnership(address to) private {
    require(to != msg.sender, "Cannot transfer to self");

    s_pendingOwner = to;

    emit OwnershipTransferRequested(s_owner, to);
  }

  /**
   * @notice validate access
   */
  function _validateOwnership() internal view {
    require(msg.sender == s_owner, "Only callable by owner");
  }

  /**
   * @notice Reverts if called by anyone other than the contract owner.
   */
  modifier onlyOwner() {
    _validateOwnership();
    _;
  }
}

/**
 * @title The ConfirmedOwner contract
 * @notice A contract with helpers for basic contract ownership.
 */
contract ConfirmedOwner is ConfirmedOwnerWithProposal {
  constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {}
}

interface AccessControllerInterface {
  function hasAccess(address user, bytes calldata data) external view returns (bool);
}

/**
 * @title SimpleWriteAccessController
 * @notice Gives access to accounts explicitly added to an access list by the
 * controller's owner.
 * @dev does not make any special permissions for externally, see
 * SimpleReadAccessController for that.
 */
contract SimpleWriteAccessController is AccessControllerInterface, ConfirmedOwner {
  bool public checkEnabled;
  mapping(address => bool) internal accessList;

  event AddedAccess(address user);
  event RemovedAccess(address user);
  event CheckAccessEnabled();
  event CheckAccessDisabled();

  constructor() ConfirmedOwner(msg.sender) {
    checkEnabled = true;
  }

  /**
   * @notice Returns the access of an address
   * @param _user The address to query
   */
  function hasAccess(address _user, bytes memory) public view virtual override returns (bool) {
    return accessList[_user] || !checkEnabled;
  }

  /**
   * @notice Adds an address to the access list
   * @param _user The address to add
   */
  function addAccess(address _user) external onlyOwner {
    if (!accessList[_user]) {
      accessList[_user] = true;

      emit AddedAccess(_user);
    }
  }

  /**
   * @notice Removes an address from the access list
   * @param _user The address to remove
   */
  function removeAccess(address _user) external onlyOwner {
    if (accessList[_user]) {
      accessList[_user] = false;

      emit RemovedAccess(_user);
    }
  }

  /**
   * @notice makes the access check enforced
   */
  function enableAccessCheck() external onlyOwner {
    if (!checkEnabled) {
      checkEnabled = true;

      emit CheckAccessEnabled();
    }
  }

  /**
   * @notice makes the access check unenforced
   */
  function disableAccessCheck() external onlyOwner {
    if (checkEnabled) {
      checkEnabled = false;

      emit CheckAccessDisabled();
    }
  }

  /**
   * @dev reverts if the caller does not have access
   */
  modifier checkAccess() {
    require(hasAccess(msg.sender, msg.data), "No access");
    _;
  }
}


Copy the contents on that page and paste it into the empty field titled "Enter the Solidity Contract Code below"


Copy in the Constructor Arguments

You do not need to provide the constructor arguments for the SimpleWriteAccessController contract, since we did not set any values when deploying the contract.


Set Miscellaneous Settings

Click the drop-down for Misc. Settings and set the Runs to 20000 (twenty-thousand)

Leave the other options as their defaults.


Once you have the above completed, click the button to verify the contract.