Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn registration into NFT #76

Merged
merged 10 commits into from
Aug 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .deployment-sample.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
mnemonic: 'mnemonic',
infuraKey: 'infuraKey',
maticKey: 'maticKey',
etherscanApiKey: 'etherscanApiKey'
}
7 changes: 2 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,8 @@ Usage: deployNewParty [options]

Options:

-i, --id <id> Id of party (obtain from UI /create page)
--ropsten Use Ropsten instead of local development network
--rinkeby Use Rinkeby instead of local development network
--kovan Use Rinkeby instead of local development network
--mainnet Use Mainnet instead of local development network
-a, --address <address> Address of party (obtain from UI /create page)
-n, --network <network> Name of the network (e.g. ropsten, mainnet, etc.)
--admins <n> Number of additional party admins to have
-c, --cancelled Whether to mark the party as cancelled
-t, --coolingPeriod [n] How long the cooling period is in seconds (default: 604800)
Expand Down
57 changes: 54 additions & 3 deletions contracts/AbstractConference.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ pragma solidity ^0.5.11;

import './GroupAdmin.sol';
import './Conference.sol';
import './Deployer.sol';
import { Utils } from './Utils.sol';
import 'openzeppelin-solidity/contracts/math/SafeMath.sol';
import 'openzeppelin-solidity/contracts/token/ERC721/ERC721.sol';

contract AbstractConference is Conference, GroupAdmin {
contract AbstractConference is Conference, GroupAdmin, ERC721 {
using SafeMath for uint256;

string public name;
Expand All @@ -24,6 +27,8 @@ contract AbstractConference is Conference, GroupAdmin {
uint256 public lastSent = 0;
uint256 public withdrawn = 0;

Deployer public deployer;

mapping (address => Participant) public participants;
mapping (uint256 => address) public participantsIndex;

Expand Down Expand Up @@ -70,15 +75,17 @@ contract AbstractConference is Conference, GroupAdmin {
* @param _limitOfParticipants The number of participant. The default is set to 20. The number can be changed by the owner of the event.
* @param _coolingPeriod The period participants should withdraw their deposit after the event ends. After the cooling period, the event owner can claim the remining deposits.
* @param _owner The owner of the event
* @param _clearFee the fee for _clearAndSend function in per-mille (e.g. _clearFee = 10 means 1% fees, _clearFee = 1 means 0.1% fees)
* @param _clearFee the fee for _clearAndSend function in per-mille (e.g. _clearFee = 10 means 1% fees, _clearFee = 1 means 0.1% fees)
* @param _deployerAddress The address of the Deployer contract.
*/
constructor (
string memory _name,
uint256 _deposit,
uint256 _limitOfParticipants,
uint256 _coolingPeriod,
address payable _owner,
uint256 _clearFee
uint256 _clearFee,
address _deployerAddress
) public {
require(_owner != address(0), 'owner address is required');
owner = _owner;
Expand All @@ -87,6 +94,7 @@ contract AbstractConference is Conference, GroupAdmin {
limitOfParticipants = _limitOfParticipants;
coolingPeriod = _coolingPeriod;
clearFee = _clearFee;
deployer = Deployer(_deployerAddress);
}


Expand All @@ -102,6 +110,8 @@ contract AbstractConference is Conference, GroupAdmin {
participantsIndex[registered] = msg.sender;
participants[msg.sender] = Participant(registered, msg.sender, false);

mint(msg.sender, registered);

emit RegisterEvent(msg.sender, registered);
}

Expand Down Expand Up @@ -324,4 +334,45 @@ contract AbstractConference is Conference, GroupAdmin {
revert('tokenAddress must be impelmented in the child class');
}

/* ERC721 implementation start */

function tokenURI(uint256 tokenId) public view returns (string memory) {
return string(abi.encodePacked(deployer.baseTokenUri(), Utils.addr2str(address(this)), '/', _tokenURI(tokenId)));
}

/**
* @dev Internal returns an URI for a given token ID.
* Throws if the token ID does not exist. May return an empty string.
* @param tokenId uint256 ID of the token to query
*/
function _tokenURI(uint256 tokenId) internal view returns (string memory) {
require(_exists(tokenId), 'ERC721Metadata: URI query for nonexistent token');
return Utils.uint2str(tokenId);
}

/**
* @dev Mints a new token.
* @param to The address that will own the minted token
* @param tokenId uint256 ID of the token to be minted
*/
function mint(address to, uint256 tokenId) internal {
_mint(to, tokenId);
}

function transferFrom(address from, address to, uint256 tokenId) public onlyActive {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you rename transferFrom to _beforeTokenTransfer you don't need to override safeTransferFrom(address from, address to, uint256 tokenId) nor safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, is it because we still use the old version of the solidity? Ok, then let's leave it as is.

require(!isRegistered(to), 'already registered');
super.transferFrom(from, to, tokenId);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use the _beforeTokenTransfer hook, you don't need to call super.transferFrom as it gets called after _beforeTokenTransfer is called.


Participant memory participant = participants[from];
participantsIndex[participant.index] = to;
participants[from] = Participant(0, address(0), false);
participants[to] = Participant(participant.index, address(uint160(to)), participant.paid);
}

function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory _data) public {
transferFrom(from, to, tokenId);
require(super._checkOnERC721Received(from, to, tokenId, _data), 'ERC721: transfer to non ERC721Receiver implementer');
}

/* ERC721 implementation end */
}
3 changes: 3 additions & 0 deletions contracts/Conference.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,7 @@ interface Conference {
function setLimitOfParticipants(uint256 _limitOfParticipants) external;
function finalize(uint256[] calldata _maps) external;
function tokenAddress() external view returns (address);

// ERC721
function tokenURI(uint256 tokenId) view external returns (string memory);
}
19 changes: 16 additions & 3 deletions contracts/Deployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ contract Deployer is Destructible, GroupAdmin {
DeployerInterface ethDeployer;
DeployerInterface erc20Deployer;
uint public clearFee;
constructor(address _ethDeployer, address _erc20Deployer, uint _clearFee) public {
string public baseTokenUri;
constructor(address _ethDeployer, address _erc20Deployer, uint _clearFee, string memory _baseTokenUri) public {
ethDeployer = DeployerInterface(_ethDeployer);
erc20Deployer = DeployerInterface(_erc20Deployer);
clearFee = _clearFee;
baseTokenUri = _baseTokenUri;
}
/**
* Notify that a new party has been deployed.
Expand All @@ -29,11 +31,20 @@ contract Deployer is Destructible, GroupAdmin {
uint indexed clearFee
);

event BaseTokenUriChanged(
string indexed uri
);

function changeClearFee(uint _clearFee) external onlyAdmin {
clearFee = _clearFee;
emit ClearFeeChanged(clearFee);
}

function changeBaseTokenUri(string calldata _baseTokenUri) external onlyAdmin{
baseTokenUri = _baseTokenUri;
emit BaseTokenUriChanged(baseTokenUri);
}

/**
* Deploy a new contract.
* @param _name The name of the event
Expand All @@ -58,7 +69,8 @@ contract Deployer is Destructible, GroupAdmin {
_coolingPeriod,
msg.sender,
_tokenAddress,
clearFee
clearFee,
address(this)
);
}else{
c = ethDeployer.deploy(
Expand All @@ -68,7 +80,8 @@ contract Deployer is Destructible, GroupAdmin {
_coolingPeriod,
msg.sender,
address(0),
clearFee
clearFee,
address(this)
);
}
emit NewParty(address(c), msg.sender);
Expand Down
3 changes: 2 additions & 1 deletion contracts/DeployerInterface.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface DeployerInterface {
uint _coolingPeriod,
address payable _ownerAddress,
address _tokenAddress,
uint256 _clearFee
uint256 _clearFee,
address _deployerAddress
)external returns(Conference c);
}
5 changes: 3 additions & 2 deletions contracts/ERC20Conference.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ contract ERC20Conference is AbstractConference {
uint256 _coolingPeriod,
address payable _owner,
address _tokenAddress,
uint256 _clearFee
uint256 _clearFee,
address _deployerAddress
)
AbstractConference(_name, _deposit, _limitOfParticipants, _coolingPeriod, _owner, _clearFee)
AbstractConference(_name, _deposit, _limitOfParticipants, _coolingPeriod, _owner, _clearFee, _deployerAddress)
public
{
require(_tokenAddress != address(0), 'token address is not set');
Expand Down
6 changes: 4 additions & 2 deletions contracts/ERC20Deployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ contract ERC20Deployer is DeployerInterface{
uint _coolingPeriod,
address payable _ownerAddress,
address _tokenAddress,
uint256 _clearFee
uint256 _clearFee,
address _deployerAddress
)external returns(Conference c){
c = new ERC20Conference(
_name,
Expand All @@ -20,7 +21,8 @@ contract ERC20Deployer is DeployerInterface{
_coolingPeriod,
_ownerAddress,
_tokenAddress,
_clearFee
_clearFee,
_deployerAddress
);
}
}
5 changes: 3 additions & 2 deletions contracts/EthConference.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ contract EthConference is AbstractConference {
uint256 _limitOfParticipants,
uint256 _coolingPeriod,
address payable _owner,
uint256 _clearFee
uint256 _clearFee,
address _deployerAddress
)
AbstractConference(_name, _deposit, _limitOfParticipants, _coolingPeriod, _owner, _clearFee)
AbstractConference(_name, _deposit, _limitOfParticipants, _coolingPeriod, _owner, _clearFee, _deployerAddress)
public
{
}
Expand Down
6 changes: 4 additions & 2 deletions contracts/EthDeployer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,17 @@ contract EthDeployer is DeployerInterface{
uint _coolingPeriod,
address payable _ownerAddress,
address /* _tokenAddress */,
uint256 _clearFee
uint256 _clearFee,
address _deployerAddress
)external returns(Conference c){
c = new EthConference(
_name,
_deposit,
_limitOfParticipants,
_coolingPeriod,
_ownerAddress,
_clearFee
_clearFee,
_deployerAddress
);
}
}
43 changes: 43 additions & 0 deletions contracts/Utils.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
pragma solidity ^0.5.11;

library Utils {
function uint2str(uint256 _i)
internal
pure
returns (string memory _uintAsString)
{
if (_i == 0) {
return '0';
}
uint256 j = _i;
uint256 len;
while (j != 0) {
len++;
j /= 10;
}
bytes memory bstr = new bytes(len);
uint256 k = len - 1;
while (_i != 0) {
bstr[k--] = bytes1(uint8(48 + (_i % 10)));
_i /= 10;
}
return string(bstr);
}

function addr2str(address _address) internal pure returns (string memory) {
return bytes2str(abi.encodePacked(_address));
}

function bytes2str(bytes memory _data) internal pure returns (string memory) {
bytes memory alphabet = '0123456789abcdef';

bytes memory str = new bytes(2 + _data.length * 2);
str[0] = '0';
str[1] = 'x';
for (uint256 i = 0; i < _data.length; i++) {
str[2 + i * 2] = alphabet[uint256(uint8(_data[i] >> 4))];
str[3 + i * 2] = alphabet[uint256(uint8(_data[i] & 0x0f))];
}
return string(str);
}
}
3 changes: 2 additions & 1 deletion hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ module.exports = {
accounts:{
count: 500,
accountsBalance: '2000000000000000000000000'
}
},
allowUnlimitedContractSize: true
},
localhost: {
url: "http://127.0.0.1:8545"
Expand Down
3 changes: 2 additions & 1 deletion migrations/2_deploy_contracts.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ let limitOfParticipants = 0; // 0 falls back to the contract default
let clearFee = 10; // 1%
let admins
const emptyAddress = '0x0000000000000000000000000000000000000000';
const baseTokenUri = 'https://kickback.events/ticket/'
// eg: truffle migrate --config '{"name":"CodeUp No..", "limitOfParticipants":15}'
if (yargs.argv.config) {
config = JSON.parse(yargs.argv.config);
Expand Down Expand Up @@ -49,7 +50,7 @@ module.exports = function(deployer) {
await deployer.deploy(ERC20Deployer);
const ethDeployer = await EthDeployer.deployed();
const erc20Deployer = await ERC20Deployer.deployed();
await deployer.deploy(Deployer, ethDeployer.address, erc20Deployer.address, clearFee);
await deployer.deploy(Deployer, ethDeployer.address, erc20Deployer.address, clearFee, baseTokenUri);
const mainDeployer = await Deployer.deployed();
console.log([name, deposit,limitOfParticipants, coolingPeriod, clearFee].join(','));
if(admins){
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
"babel-preset-env": "^1.7.0",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"chai-string": "^1.5.0",
"commander": "^7.2.0",
"coveralls": "^3.1.0",
"eth-gas-reporter": "^0.2.22",
Expand Down
Loading