/execution-permissions

Utility contract for setting/enforcing execution permissions per function

Primary LanguageTypeScriptGNU Affero General Public License v3.0AGPL-3.0

Execution Permissions

Utility contract for setting/enforcing execution permissions per function

Byte size of Execution Permissions Open Issues Open Pull Requests Latest commits GitHub Actions Build Status License



Requirements

Prerequisites and/or dependencies that this project needs to function properly

This project utilizes Truffle for organization of source code and tests, thus it is recommended to install Truffle globally to your current user account

npm install -g truffle

... Or to your project root directory

cd your_project

npm install truffle

Quick Start

Perhaps as easy as one, 2.0,...

NPM and Truffle are recommended for importing and managing dependencies

cd your_project

npm install @solidity-utilities/execution-permissions

Note, source code will be located within the node_modules/@solidity-utilities/execution-permissions directory of your_project root

Solidity contracts may then import code via similar syntax as shown

import {
  ExecutionPermissions
} from "@solidity-utilities/execution-permissions/contracts/ExecutionPermissions.sol";

import {
  IExecutionPermissions,
  BatchPermissionEntry
} from "@solidity-utilities/execution-permissions/contracts/interfaces/IExecutionPermissions.sol";

Note, above paths are not relative (ie. there's no ./ preceding the file path) which causes Truffle to search the node_modules subs-directories

Review the Truffle -- Package Management via NPM documentation for more details.


In the future, after beta testers have reported bugs and feature requests, it should be possible to link the deployed ExecutionPermissions via Truffle migration similar to the following.

migrations/2_example_usage.js

const refExecutionPermissions = "0x0...0";
const ExampleUsage = artifacts.require("ExampleUsage");

module.exports = (deployer, _network, _accounts) {
  deployer.deploy(ExampleUsage, refExecutionPermissions);
};

Usage

How to utilize this repository

Write contract(s) that make use of, and extend, ExecutionPermissions features.

ExampleUsage contract

Example contract that utilizes existing ExecutionPermissions contract

// SPDX-License-Identifier: AGPL-3.0
pragma solidity >=0.4.22 <0.9.0;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";

import {
  IExecutionPermissions,
  BatchPermissionEntry
} from "@solidity-utilities/execution-permissions/contracts/interfaces/IExecutionPermissions.sol";

/// @title Example of how to utilize ExecutionPermissions features
/// @author S0AndS0
contract ExampleUsage is Ownable {
    address private _permissionStore;

    mapping(address => uint256) public account_score;

    // Store referenced to `ExecutionPermissions` contract
    constructor(address permissionStore_) Ownable() {
        _permissionStore = permissionStore_;
    }

    // Restrict execution to only permitted callers
    modifier onlyPermitted() {
        require(
            IExecutionPermissions(_permissionStore).isPermitted(
                bytes4(msg.data),
                msg.sender
            ),
            "ExampleUsage: sender not permitted"
        );
        _;
    }

    // Example of restricted function
    function setScore(uint256 value) external payable onlyPermitted {
        account_score[msg.sender] = value;
    }

    // Allow only contract owner to modify own registration state
    function setRegistered(bool state) external payable virtual onlyOwner {
        IExecutionPermissions(_permissionStore).setRegistered(state);
    }

    // Allow only contract owner to modify permissions
    function setBatchPermission(BatchPermissionEntry[] memory entries)
        external
        payable
        virtual
        onlyOwner
    {
        IExecutionPermissions(_permissionStore).setBatchPermission(entries);
    }

    // Allow only contract owner to modify permissions
    function setTargetPermission(
        bytes4 target,
        address caller,
        bool state
    ) external payable virtual onlyOwner {
        IExecutionPermissions(_permissionStore).setTargetPermission(
            target,
            caller,
            state
        );
    }
}

Tip; review the ts/test, and test/solidity, sub-directories for extensive usage examples


Networks

Anyone may utilize the contract on-chain via the following network addresses

migrations/1000_ExampleUsage.js (example)

'use strict';

module.exports = (deployer, network, accounts) => {
  const ExampleUsage = artifacts.require('ExampleUsage');

  const parameters = {
    permissionStore: '0x90f94E4Fa212Aafb4d9528c3A064815B3378c8b9',
  };

  deployer.deploy(ExampleUsage, ...Object.values(parameters));
};

Ethereum Main

Address: 0x90f94E4Fa212Aafb4d9528c3A064815B3378c8b9


API

Application Programming Interfaces for Solidity smart contracts


Contracts ExecutionPermissions and IExecutionPermissions

Utility contract for setting/enforcing execution permissions per function

Source


Method isPermitted(bytes4,address)

Check execution permissions of target function for given caller

Source

Parameters

  • target {bytes4} Function ID to check
  • caller {address} Original msg.sender of targeted function

Throws -> {Error} "ExecutionPermissions: instance not registered"


Method isPermitted(string,address)

Check execution permissions of target function for given caller

Source

Parameters

  • target {string} Function signature to check
  • caller {address} Original msg.sender of targeted function

Throws -> {Error} "ExecutionPermissions: instance not registered"

Developer note -> Note will cost more gas than isPermitted(bytes4,address) due to implicit conversion of function signature string to ID


Method setBatchPermission(BatchPermissionEntry[])

Assign multiple permission entries in one transaction

Source

Parameters

  • BatchPermissionEntry {array} entries List of permissions to assign

Throws -> {Error} "ExecutionPermissions: instance not registered"

Developer note -> Note may cost less gas due to fewer initialization transaction fees of multiple setTargetPermission(bytes4,address,bool) calls


Method setTargetPermission(bytes4,address,bool)

Assign single function caller permission state

Source

Parameters

  • BatchPermissionEntry {array} entries List of permissions to assign
  • target {bytes4} Function ID to set caller permission
  • caller {address} Original msg.sender of targeted function
  • state {boolean} Value to assign for function caller interaction

Throws -> {Error} "ExecutionPermissions: instance not registered"


Method setRegistered(bool)

Set registration state for calling contract instance

Source

Parameters

  • state {boolean} Set true for registered and false for unregistered (default)

Throws -> {Error} "ExecutionPermissions: instance not initialized"


Method setRegistered(address,bool)

Set registration state for referenced contract instance

Source

Parameters

  • ref {address} Contract instance owned by msg.sender
  • state {boolean} Set true for registered and false for unregistered (default)

Throws -> {Error} "ExecutionPermissions: instance not initialized" Throws -> {Error} "ExecutionPermissions: instance does not implement .owner()" Throws -> {Error} "ExecutionPermissions: not instance owner"


Method tip()

Show some support developers of this contract

Source


Method withdraw(address,uint256)

Allow owner of ExecutionPermissions to receive tips

Source

Parameters

  • to {address} Where to send Ethereum
  • amount {uint256} Measured in Wei

Throws -> {Error} "ExecutionPermissions: caller not owner" Throws -> {Error} "ExecutionPermissions: transfer failed"


Method nominateOwner(address)

Initiate transfer of contract ownership

Source

Parameters

  • newOwner {address} Account that may claim ownership of contract

Throws -> {Error} "ExecutionPermissions: caller not owner" Throws -> {Error} "ExecutionPermissions: new owner cannot be zero address"


Method claimOwnership

Accept transfer of contract ownership

Source

Throws -> {Error} "ExecutionPermissions: new owner cannot be zero address" Throws -> {Error} "ExecutionPermissions: sender not nominated"


Storage permissions(address,bytes4,address)

Check execution permissions of referenced contract function for given caller

Source

Parameters

  • ref {address} Contract address with target function
  • target {bytes4} Function ID to check
  • caller {address} Original msg.sender of targeted function

Storage registered(address)

Check registration status of referenced contract

Source

Parameters

  • ref {address} Contract address to check registration state

Returns -> {boolean} State of ref registration


Storage owner()

Obtain current owner address

Source

Returns -> {address} Current owner of contract instance


Storage nominated_owner()

Obtain new owner nominated address

Source

Returns -> {address} Last nominated address of new contract instance owner


Notes

This repository may not be feature complete and/or fully functional, Pull Requests that add features or fix bugs are certainly welcomed.


Contributing

Options for contributing to execution-permissions and solidity-utilities


Forking

Start making a Fork of this repository to an account that you have write permissions for.

  • Add remote for fork URL. The URL syntax is git@github.com:<NAME>/<REPO>.git...
cd ~/git/hub/solidity-utilities/execution-permissions

git remote add fork git@github.com:<NAME>/execution-permissions.git
  • Commit your changes and push to your fork, eg. to fix an issue...
cd ~/git/hub/solidity-utilities/execution-permissions


git commit -F- <<'EOF'
:bug: Fixes #42 Issue


**Edits**


- `<SCRIPT-NAME>` script, fixes some bug reported in issue
EOF


git push fork main

Note, the -u option may be used to set fork as the default remote, eg. git push -u fork main however, this will also default the fork remote for pulling from too! Meaning that pulling updates from origin must be done explicitly, eg. git pull origin main

  • Then on GitHub submit a Pull Request through the Web-UI, the URL syntax is https://github.com/<NAME>/<REPO>/pull/new/<BRANCH>

Note; to decrease the chances of your Pull Request needing modifications before being accepted, please check the dot-github repository for detailed contributing guidelines.


Sponsor

Thanks for even considering it!

Via Liberapay you may [![sponsor__shields_io__liberapay]][sponsor__link__liberapay] on a repeating basis.

Regardless of if you're able to financially support projects such as execution-permissions that solidity-utilities maintains, please consider sharing projects that are useful with others, because one of the goals of maintaining Open Source repositories is to provide value to the community.


Attribution


License

Utility contract for setting/enforcing execution permissions per function
Copyright (C) 2022 S0AndS0

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, version 3 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <https://www.gnu.org/licenses/>.

For further details review full length version of AGPL-3.0 License.