Skip to content

Commit cbe3a1e

Browse files
authored
Merge pull request #879 from oceanprotocol/feature/refactor_access_lists
Feature/refactor_access_lists
2 parents 3fe47d9 + da662a1 commit cbe3a1e

File tree

13 files changed

+559
-118
lines changed

13 files changed

+559
-118
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = v2.1.0
2+
current_version = v2.2.0
33
commit = True
44
tag = True
55

addresses/address.json

100644100755
Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -269,14 +269,16 @@
269269
"1": "0x519d462294958A935D34351b3ad9F98cCAB0b7f8",
270270
"2": "0x2bCa501a6f9FB8a96f1b7B09D4f74A32ACAa7584",
271271
"3": "0xf00c16665b79F23c04e5c8652Fe9853046b987c8",
272-
"4": "0x89b752C3e272feBA17B363EaaBFe0d653cF75bE7"
272+
"4": "0x89b752C3e272feBA17B363EaaBFe0d653cF75bE7",
273+
"5": "0xb4914dfeC7f70C708673620eDF6d8839F81E7612"
273274
},
274275
"ERC721Template": {
275276
"1": "0x9Ab15cc945b2B58A51384539211dE8a88a1355E8"
276277
},
277278
"Dispenser": "0xbde8224d15885c2E46Be665b9392E619cD142de8",
278279
"ERC721Factory": "0x315ef329D214cde5cE7C206104aC35B1fe66bb8c",
279-
"PredictoorHelper": "0x2e4cb19faD077768fDcB04Bc0549AB76BE8eA63F"
280+
"PredictoorHelper": "0x2e4cb19faD077768fDcB04Bc0549AB76BE8eA63F",
281+
"AccessListFactory": "0xdA412123a3Cc0D921bcf7246f8742e3b7c3E7b94"
280282
},
281283
"sepolia": {
282284
"chainId": 11155111,
@@ -307,7 +309,8 @@
307309
"1": "0xDBDa486d8fE29F75e9Ca858F438b380Fc14b1232",
308310
"2": "0xF6410bf5d773C7a41ebFf972f38e7463FA242477",
309311
"3": "0x1B083D8584dd3e6Ff37d04a6e7e82b5F622f3985",
310-
"4": "0x4dD281EB67DED07E76E413Df16176D66ae69e240"
312+
"4": "0x4dD281EB67DED07E76E413Df16176D66ae69e240",
313+
"5": "0xA4E108a4fa07C931cFe4bF2c1c6f9C1579d5a819"
311314
},
312315
"ERC721Template": {
313316
"1": "0x69B6E54Ad2b3c2801d11d8Ad56ea1d892555b776"
@@ -316,7 +319,8 @@
316319
"ERC721Factory": "0x80E63f73cAc60c1662f27D2DFd2EA834acddBaa8",
317320
"DFRewards": "0xc37F8341Ac6e4a94538302bCd4d49Cf0852D30C0",
318321
"DFStrategyV1": "0x3c21a90599b5B7f37014cA5Bf30d3f1b73d7e391",
319-
"PredictoorHelper": "0xE9397625Df9B63f0C152f975234b7988b54710B8"
322+
"PredictoorHelper": "0xE9397625Df9B63f0C152f975234b7988b54710B8",
323+
"AccessListFactory": "0x12bB8D85a091A69A07E22E52d4567dBB91568f52"
320324
},
321325
"optimism_sepolia": {
322326
"chainId": 11155420,
@@ -359,7 +363,7 @@
359363
"Router": "0x4Ede1776D6B75de6c907172Abc0453a3C8AB372a",
360364
"FixedPrice": "0x8372715D834d286c9aECE1AcD51Da5755B32D505",
361365
"ERC20Template": {
362-
"1": "0x02eCd3850B53b1BA8dbCdD146C963cC27f27Dd3C",
366+
"1": "0x02eCd3850B53b1BA8dbCdD146C963cC27f27Dd3C",
363367
"2": "0x23Efb300c8778d6842bB0cCBD07D356eCeB97070"
364368
},
365369
"ERC721Template": {

contracts/accesslists/AccessList.sol

Lines changed: 120 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,36 +9,141 @@ import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
99
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
1010
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
1111
import "@openzeppelin/contracts/utils/Counters.sol";
12-
import "@openzeppelin/contracts/access/Ownable.sol";
1312

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

22-
contract AccessList is Ownable, ERC721Enumerable,ERC721URIStorage {
22+
contract AccessList is ERC721Enumerable,ERC721URIStorage {
2323
using Counters for Counters.Counter;
2424
Counters.Counter private _tokenIds;
25+
bool private initialized;
26+
address private _owner;
27+
string private _name;
28+
string private _symbol;
29+
bool public transferable;
2530

26-
27-
event NewAccessList(
28-
address indexed contractAddress,
29-
address indexed owner
30-
);
3131
event AddressAdded(
3232
address indexed wallet,
3333
uint256 tokenId
3434
);
3535
event AddressRemoved(
3636
uint256 tokenId
3737
);
38+
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
39+
constructor()
40+
ERC721("","") {
41+
42+
}
43+
/**
44+
* @dev Throws if called by any account other than the owner.
45+
*/
46+
modifier onlyOwner() {
47+
_checkOwner();
48+
_;
49+
}
50+
51+
/**
52+
* @dev Returns the address of the current owner.
53+
*/
54+
function owner() public view returns (address) {
55+
return _owner;
56+
}
57+
58+
/**
59+
* @dev Throws if the sender is not the owner.
60+
*/
61+
function _checkOwner() internal view {
62+
require(owner() == _msgSender(), "Ownable: caller is not the owner");
63+
}
64+
65+
/**
66+
* @dev Leaves the contract without owner. It will not be possible to call
67+
* `onlyOwner` functions. Can only be called by the current owner.
68+
*
69+
* NOTE: Renouncing ownership will leave the contract without an owner,
70+
* thereby disabling any functionality that is only available to the owner.
71+
*/
72+
function renounceOwnership() public onlyOwner {
73+
_transferOwnership(address(0));
74+
}
3875

39-
constructor(string memory _name, string memory _symbol)
40-
ERC721(_name, _symbol) {
41-
emit NewAccessList(address(this),_msgSender());
76+
/**
77+
* @dev Transfers ownership of the contract to a new account (`newOwner`).
78+
* Can only be called by the current owner.
79+
*/
80+
function transferOwnership(address newOwner) public onlyOwner {
81+
require(newOwner != address(0), "Ownable: new owner is the zero address");
82+
_transferOwnership(newOwner);
83+
}
84+
85+
/**
86+
* @dev Transfers ownership of the contract to a new account (`newOwner`).
87+
* Internal function without access restriction.
88+
*/
89+
function _transferOwnership(address newOwner) internal {
90+
address oldOwner = _owner;
91+
_owner = newOwner;
92+
emit OwnershipTransferred(oldOwner, newOwner);
93+
}
94+
/* @dev initialize
95+
* Calls private _initialize function. Only if contract is not initialized.
96+
This function mints an NFT (tokenId=1) to the owner and add owner as Manager Role
97+
* @param owner NFT Owner
98+
* @param name_ NFT name
99+
* @param symbol_ NFT Symbol
100+
* @param transferable_ if set to false, this NFT is non-transferable
101+
102+
@return boolean
103+
*/
104+
105+
function initialize(
106+
address owner_,
107+
string calldata name_,
108+
string calldata symbol_,
109+
bool transferable_,
110+
address[] memory user,
111+
string[] memory _tokenURI
112+
) external returns (bool) {
113+
require(
114+
!initialized,
115+
"Already initialized"
116+
);
117+
_name = name_;
118+
_symbol = symbol_;
119+
_owner=owner_;
120+
initialized = true;
121+
transferable = transferable_;
122+
if(user.length==_tokenURI.length && _tokenURI.length>0){
123+
uint256 i;
124+
for(i=0;i<user.length;i++){
125+
_add(user[i],_tokenURI[i]);
126+
}
127+
}
128+
return(true);
129+
}
130+
131+
/**
132+
* @dev name
133+
* It returns the token name.
134+
* @return Datatoken name.
135+
*/
136+
function name() public view override returns (string memory) {
137+
return _name;
138+
}
139+
140+
/**
141+
* @dev symbol
142+
* It returns the token symbol.
143+
* @return Datatoken symbol.
144+
*/
145+
function symbol() public view override returns (string memory) {
146+
return _symbol;
42147
}
43148

44149
function tokenURI(uint256 tokenId)
@@ -61,7 +166,8 @@ contract AccessList is Ownable, ERC721Enumerable,ERC721URIStorage {
61166
internal
62167
override(ERC721,ERC721Enumerable)
63168
{
64-
require(from == address(0) || to == address(0), "Token not transferable");
169+
if(transferable == false)
170+
require(from == address(0) || to == address(0), "Token not transferable");
65171
super._beforeTokenTransfer(from, to, tokenId, batchSize);
66172
}
67173

@@ -92,7 +198,7 @@ contract AccessList is Ownable, ERC721Enumerable,ERC721URIStorage {
92198
}
93199

94200
function burn(uint256 tokenId) public {
95-
require(_msgSender() == super.owner() || _msgSender()==super._ownerOf(tokenId),"ERC721: Not owner");
201+
require(_msgSender() == owner() || _msgSender()==super._ownerOf(tokenId),"ERC721: Not owner");
96202
emit AddressRemoved(tokenId);
97203
_burn(tokenId);
98204
}
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
pragma solidity 0.8.12;
2+
// Copyright BigchainDB GmbH and Ocean Protocol contributors
3+
// SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
4+
// Code is Apache-2.0 and docs are CC-BY-4.0
5+
6+
import "../utils/Deployer.sol";
7+
import "@openzeppelin/contracts/access/Ownable.sol";
8+
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
9+
10+
interface IAccessList{
11+
function initialize(address, string calldata, string calldata,
12+
bool,address[] memory,string[] memory) external returns (bool);
13+
function transferable() external view returns (bool);
14+
15+
}
16+
/**
17+
* @title DTFactory contract
18+
* @author Ocean Protocol Team
19+
*
20+
* @dev Implementation of Ocean datatokens Factory
21+
*
22+
* DTFactory deploys datatoken proxy contracts.
23+
* New datatoken proxy contracts are links to the template contract's bytecode.
24+
* Proxy contract functionality is based on Ocean Protocol custom implementation of ERC1167 standard.
25+
*/
26+
contract AccessListFactory is Deployer, Ownable, ReentrancyGuard {
27+
address templateAddress;
28+
mapping(address => address) public accessListDeployedContracts;
29+
30+
event NewAccessList(
31+
address indexed contractAddress,
32+
address indexed owner
33+
);
34+
35+
/**
36+
* @dev Returns true if `account` is a contract.
37+
*
38+
* [IMPORTANT]
39+
* ====
40+
* It is unsafe to assume that an address for which this function returns
41+
* false is an externally-owned account (EOA) and not a contract.
42+
*
43+
* Among others, `isContract` will return false for the following
44+
* types of addresses:
45+
*
46+
* - an externally-owned account
47+
* - a contract in construction
48+
* - an address where a contract will be created
49+
* - an address where a contract lived, but was destroyed
50+
* ====
51+
*/
52+
function _isContract(address account) internal view returns (bool) {
53+
// This method relies on extcodesize, which returns 0 for contracts in
54+
// construction, since the code is only stored at the end of the
55+
// constructor execution.
56+
57+
uint256 size;
58+
// solhint-disable-next-line no-inline-assembly
59+
assembly {
60+
size := extcodesize(account)
61+
}
62+
return size > 0;
63+
}
64+
/**
65+
* @dev constructor
66+
* Called on contract deployment. Could not be called with zero address parameters.
67+
* @param _template refers to the address of a deployed access list contract.
68+
*/
69+
constructor(
70+
address _template
71+
) {
72+
require(
73+
_template != address(0) && _isContract(_template),
74+
"Invalid template"
75+
);
76+
templateAddress=_template;
77+
}
78+
79+
80+
/**
81+
* @dev deployAccessListContract
82+
*
83+
* @param name NFT name
84+
* @param symbol NFT Symbol
85+
* @param transferable if NFT is transferable. Cannot be changed afterwards
86+
* @param owner owner of the NFT
87+
* @param user array of users to add on the list
88+
* @param _tokenURI array of uris for each of the users to be added on the list
89+
*/
90+
91+
function deployAccessListContract(
92+
string calldata name,
93+
string calldata symbol,
94+
bool transferable,
95+
address owner,
96+
address[] memory user,
97+
string[] memory _tokenURI
98+
) public returns (address token) {
99+
token = deploy(templateAddress);
100+
101+
require(
102+
token != address(0),
103+
"Failed to deploy new access list"
104+
);
105+
106+
accessListDeployedContracts[token] = token;
107+
emit NewAccessList(token,owner);
108+
IAccessList tokenInstance = IAccessList(token);
109+
require(
110+
tokenInstance.initialize(
111+
owner,
112+
name,
113+
symbol,
114+
transferable,
115+
user,
116+
_tokenURI
117+
),
118+
"Unable to initialize access list"
119+
);
120+
121+
122+
}
123+
124+
125+
/**
126+
* @dev change the template address
127+
Only Owner can call it
128+
* @param _newTemplateAddress new template address
129+
*/
130+
131+
// function to activate a disabled token.
132+
function changeTemplateAddress(address _newTemplateAddress) external onlyOwner {
133+
require(
134+
_newTemplateAddress != address(0) && _isContract(_newTemplateAddress),
135+
"Invalid template"
136+
);
137+
templateAddress=_newTemplateAddress;
138+
}
139+
140+
function isDeployed(address contractAddress) public view returns (bool){
141+
if(accessListDeployedContracts[contractAddress] == contractAddress) return true;
142+
return false;
143+
}
144+
function isSoulBound(address contractAddress) external view returns (bool){
145+
require(isDeployed(contractAddress)==true,"Not deployed by factory");
146+
return(!(IAccessList(contractAddress).transferable()));
147+
}
148+
149+
}

0 commit comments

Comments
 (0)