Skip to content

Commit

Permalink
Merge pull request #879 from oceanprotocol/feature/refactor_access_lists
Browse files Browse the repository at this point in the history
Feature/refactor_access_lists
  • Loading branch information
alexcos20 authored Sep 3, 2024
2 parents 3fe47d9 + da662a1 commit cbe3a1e
Show file tree
Hide file tree
Showing 13 changed files with 559 additions and 118 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = v2.1.0
current_version = v2.2.0
commit = True
tag = True

Expand Down
14 changes: 9 additions & 5 deletions addresses/address.json
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -269,14 +269,16 @@
"1": "0x519d462294958A935D34351b3ad9F98cCAB0b7f8",
"2": "0x2bCa501a6f9FB8a96f1b7B09D4f74A32ACAa7584",
"3": "0xf00c16665b79F23c04e5c8652Fe9853046b987c8",
"4": "0x89b752C3e272feBA17B363EaaBFe0d653cF75bE7"
"4": "0x89b752C3e272feBA17B363EaaBFe0d653cF75bE7",
"5": "0xb4914dfeC7f70C708673620eDF6d8839F81E7612"
},
"ERC721Template": {
"1": "0x9Ab15cc945b2B58A51384539211dE8a88a1355E8"
},
"Dispenser": "0xbde8224d15885c2E46Be665b9392E619cD142de8",
"ERC721Factory": "0x315ef329D214cde5cE7C206104aC35B1fe66bb8c",
"PredictoorHelper": "0x2e4cb19faD077768fDcB04Bc0549AB76BE8eA63F"
"PredictoorHelper": "0x2e4cb19faD077768fDcB04Bc0549AB76BE8eA63F",
"AccessListFactory": "0xdA412123a3Cc0D921bcf7246f8742e3b7c3E7b94"
},
"sepolia": {
"chainId": 11155111,
Expand Down Expand Up @@ -307,7 +309,8 @@
"1": "0xDBDa486d8fE29F75e9Ca858F438b380Fc14b1232",
"2": "0xF6410bf5d773C7a41ebFf972f38e7463FA242477",
"3": "0x1B083D8584dd3e6Ff37d04a6e7e82b5F622f3985",
"4": "0x4dD281EB67DED07E76E413Df16176D66ae69e240"
"4": "0x4dD281EB67DED07E76E413Df16176D66ae69e240",
"5": "0xA4E108a4fa07C931cFe4bF2c1c6f9C1579d5a819"
},
"ERC721Template": {
"1": "0x69B6E54Ad2b3c2801d11d8Ad56ea1d892555b776"
Expand All @@ -316,7 +319,8 @@
"ERC721Factory": "0x80E63f73cAc60c1662f27D2DFd2EA834acddBaa8",
"DFRewards": "0xc37F8341Ac6e4a94538302bCd4d49Cf0852D30C0",
"DFStrategyV1": "0x3c21a90599b5B7f37014cA5Bf30d3f1b73d7e391",
"PredictoorHelper": "0xE9397625Df9B63f0C152f975234b7988b54710B8"
"PredictoorHelper": "0xE9397625Df9B63f0C152f975234b7988b54710B8",
"AccessListFactory": "0x12bB8D85a091A69A07E22E52d4567dBB91568f52"
},
"optimism_sepolia": {
"chainId": 11155420,
Expand Down Expand Up @@ -359,7 +363,7 @@
"Router": "0x4Ede1776D6B75de6c907172Abc0453a3C8AB372a",
"FixedPrice": "0x8372715D834d286c9aECE1AcD51Da5755B32D505",
"ERC20Template": {
"1": "0x02eCd3850B53b1BA8dbCdD146C963cC27f27Dd3C",
"1": "0x02eCd3850B53b1BA8dbCdD146C963cC27f27Dd3C",
"2": "0x23Efb300c8778d6842bB0cCBD07D356eCeB97070"
},
"ERC721Template": {
Expand Down
134 changes: 120 additions & 14 deletions contracts/accesslists/AccessList.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,141 @@ import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/**
* @title AccessList
*
* @dev AccessList is an soul bound ERC721 used to build access lists (allow or deny)
* Only owner can mint and also burn (ie: remove address from a list)
* @dev AccessList is an optional soul bound/non-sould bound
* ERC721 used to build access lists (allow or deny)
* Only owner can mint
* Each token id has it's own metadata
*/

contract AccessList is Ownable, ERC721Enumerable,ERC721URIStorage {
contract AccessList is ERC721Enumerable,ERC721URIStorage {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
bool private initialized;
address private _owner;
string private _name;
string private _symbol;
bool public transferable;


event NewAccessList(
address indexed contractAddress,
address indexed owner
);
event AddressAdded(
address indexed wallet,
uint256 tokenId
);
event AddressRemoved(
uint256 tokenId
);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor()
ERC721("","") {

}
/**
* @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 returns (address) {
return _owner;
}

/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view {
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 onlyOwner {
_transferOwnership(address(0));
}

constructor(string memory _name, string memory _symbol)
ERC721(_name, _symbol) {
emit NewAccessList(address(this),_msgSender());
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public 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 {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/* @dev initialize
* Calls private _initialize function. Only if contract is not initialized.
This function mints an NFT (tokenId=1) to the owner and add owner as Manager Role
* @param owner NFT Owner
* @param name_ NFT name
* @param symbol_ NFT Symbol
* @param transferable_ if set to false, this NFT is non-transferable
@return boolean
*/

function initialize(
address owner_,
string calldata name_,
string calldata symbol_,
bool transferable_,
address[] memory user,
string[] memory _tokenURI
) external returns (bool) {
require(
!initialized,
"Already initialized"
);
_name = name_;
_symbol = symbol_;
_owner=owner_;
initialized = true;
transferable = transferable_;
if(user.length==_tokenURI.length && _tokenURI.length>0){
uint256 i;
for(i=0;i<user.length;i++){
_add(user[i],_tokenURI[i]);
}
}
return(true);
}

/**
* @dev name
* It returns the token name.
* @return Datatoken name.
*/
function name() public view override returns (string memory) {
return _name;
}

/**
* @dev symbol
* It returns the token symbol.
* @return Datatoken symbol.
*/
function symbol() public view override returns (string memory) {
return _symbol;
}

function tokenURI(uint256 tokenId)
Expand All @@ -61,7 +166,8 @@ contract AccessList is Ownable, ERC721Enumerable,ERC721URIStorage {
internal
override(ERC721,ERC721Enumerable)
{
require(from == address(0) || to == address(0), "Token not transferable");
if(transferable == false)
require(from == address(0) || to == address(0), "Token not transferable");
super._beforeTokenTransfer(from, to, tokenId, batchSize);
}

Expand Down Expand Up @@ -92,7 +198,7 @@ contract AccessList is Ownable, ERC721Enumerable,ERC721URIStorage {
}

function burn(uint256 tokenId) public {
require(_msgSender() == super.owner() || _msgSender()==super._ownerOf(tokenId),"ERC721: Not owner");
require(_msgSender() == owner() || _msgSender()==super._ownerOf(tokenId),"ERC721: Not owner");
emit AddressRemoved(tokenId);
_burn(tokenId);
}
Expand Down
149 changes: 149 additions & 0 deletions contracts/accesslists/AccessListFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
pragma solidity 0.8.12;
// Copyright BigchainDB GmbH and Ocean Protocol contributors
// SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
// Code is Apache-2.0 and docs are CC-BY-4.0

import "../utils/Deployer.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

interface IAccessList{
function initialize(address, string calldata, string calldata,
bool,address[] memory,string[] memory) external returns (bool);
function transferable() external view returns (bool);

}
/**
* @title DTFactory contract
* @author Ocean Protocol Team
*
* @dev Implementation of Ocean datatokens Factory
*
* DTFactory deploys datatoken proxy contracts.
* New datatoken proxy contracts are links to the template contract's bytecode.
* Proxy contract functionality is based on Ocean Protocol custom implementation of ERC1167 standard.
*/
contract AccessListFactory is Deployer, Ownable, ReentrancyGuard {
address templateAddress;
mapping(address => address) public accessListDeployedContracts;

event NewAccessList(
address indexed contractAddress,
address indexed owner
);

/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function _isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.

uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev constructor
* Called on contract deployment. Could not be called with zero address parameters.
* @param _template refers to the address of a deployed access list contract.
*/
constructor(
address _template
) {
require(
_template != address(0) && _isContract(_template),
"Invalid template"
);
templateAddress=_template;
}


/**
* @dev deployAccessListContract
*
* @param name NFT name
* @param symbol NFT Symbol
* @param transferable if NFT is transferable. Cannot be changed afterwards
* @param owner owner of the NFT
* @param user array of users to add on the list
* @param _tokenURI array of uris for each of the users to be added on the list
*/

function deployAccessListContract(
string calldata name,
string calldata symbol,
bool transferable,
address owner,
address[] memory user,
string[] memory _tokenURI
) public returns (address token) {
token = deploy(templateAddress);

require(
token != address(0),
"Failed to deploy new access list"
);

accessListDeployedContracts[token] = token;
emit NewAccessList(token,owner);
IAccessList tokenInstance = IAccessList(token);
require(
tokenInstance.initialize(
owner,
name,
symbol,
transferable,
user,
_tokenURI
),
"Unable to initialize access list"
);


}


/**
* @dev change the template address
Only Owner can call it
* @param _newTemplateAddress new template address
*/

// function to activate a disabled token.
function changeTemplateAddress(address _newTemplateAddress) external onlyOwner {
require(
_newTemplateAddress != address(0) && _isContract(_newTemplateAddress),
"Invalid template"
);
templateAddress=_newTemplateAddress;
}

function isDeployed(address contractAddress) public view returns (bool){
if(accessListDeployedContracts[contractAddress] == contractAddress) return true;
return false;
}
function isSoulBound(address contractAddress) external view returns (bool){
require(isDeployed(contractAddress)==true,"Not deployed by factory");
return(!(IAccessList(contractAddress).transferable()));
}

}
Loading

0 comments on commit cbe3a1e

Please sign in to comment.