Actions

SimpleWriteAccessController Deployment: Difference between revisions

From Chainlink Community Wiki

No edit summary
No edit summary
Line 12: Line 12:
[[File:NewRemixProject.png|frameless|411x411px]]
[[File:NewRemixProject.png|frameless|411x411px]]


Once you have an empty doc, paste in the below contract:
Once you have an empty doc, paste in the contract in the drop-down below:


<pre style="white-space:pre-wrap; width:100%; border:1px solid lightgrey; background:black; color:white;">// SPDX-License-Identifier: MIT
 
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;
pragma solidity ^0.8.0;


Line 193: Line 197:
     _;
     _;
   }
   }
}</pre>
}</pre></div>
</div>


It should look like the below image:
It should look like the below image:

Revision as of 21:07, 30 May 2022

The purpose of this page is to provide highly detailed instructions on how to deploy the SimpleWriteAccessController.

If you're here to deploy your own OCR Aggregator, be sure to keep track of which SimpleWriteAccessController you want to use for each purpose.

Deploying the SimpleWriteAccessController Via Remix

Import the Contract into Remix

Navigate to remix.ethereum.org

Once there, create a new doc by clicking on the little page icon

NewRemixProject.png

Once you have an empty doc, paste in the contract in the drop-down below:


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");
    _;
  }
}

It should look like the below image:

ImportedSimpleWriteAccessController.png

With the contract imported into remix, We'll need to compile it


Compile the Contract

Once Pasted into Remix, navigate to the Compile page.

NavigateToCompile.png

In the image above, you can see that the COMPILER version is 0.7.6+...

When deploying the SimpleWriteAccessController.sol contract, we want to be sure that the version selected here is 0.8.0+commit.c7dfd78e

With the correct version selected, go ahead and compile the contract by clicking the blue button with the circular arrows

RemixCompileButton.png

Once that succeeds, we can then deploy the contract.


Deploy the Contract

With the contract compiled, we then need to navigate to the Deploy & run transactions tab

DeployContractPage.png

Once here, we want to be sure to adjust a couple things before deploying the contract.

First, assuming we are deploying this contract via metamask we want to change the ENVIRONMENT to Injected Web3

ChangeDeploymentEnvironment.png

The last thing we need to do before deploying the contract is change the CONTRACT we're actually deploying.

Just click the drop down and select SimpleWriteAccessController

SelectSimpleWriteAccessController.png

Next we just click the Orange deploy button!

DeployButton.png


Interacting With Deployed Contract

If you want to add a specific address or addresses to the to the SimpleWriteAccessController, we can drop down the addAccess section and paste in the desired address(es).

Once you've done that, click the transact button

AddAccess.png