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

Contracts: Enable registration of recipients in factory contract #40

Merged
merged 2 commits into from
May 30, 2020
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
6 changes: 5 additions & 1 deletion contracts/buidler.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ const config: BuidlerConfig = {
tests: "tests"
},
solc: {
version: "0.6.4"
version: "0.6.4",
optimizer: {
enabled: true,
runs: 10000
}
},
typechain: {
outDir: "build/types",
Expand Down
22 changes: 22 additions & 0 deletions contracts/contracts/FundingRoundFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol';
contract FundingRoundFactory is Ownable {
using SafeERC20 for IERC20;

// Constants
uint256 private constant MACI_MAX_VOTE_OPTIONS = 16;

// State
mapping(address => string) public recipients;
uint256 private recipientCount = 0;

address public coordinator;
address public maci;
IERC20 public nativeToken;
Expand All @@ -33,6 +40,8 @@ contract FundingRoundFactory is Ownable {

mapping(address => address) private maciByRound;

// Events
event RecipientAdded(address indexed _fundingAddress, string _name);
event NewToken(address _token);
event NewRound(address _round);
event RoundFinalized();
Expand All @@ -48,6 +57,19 @@ contract FundingRoundFactory is Ownable {
endRound();
}

function addRecipient(address _fundingAddress, string memory _name)
public
onlyOwner
{
require(_fundingAddress != address(0), 'Factory: Recipient address is zero');
require(bytes(_name).length != 0, 'Factory: Recipient name is empty string');
require(bytes(recipients[_fundingAddress]).length == 0, 'Factory: Recipient already registered');
require(recipientCount < MACI_MAX_VOTE_OPTIONS, 'Factory: Recipient limit reached');
recipients[_fundingAddress] = _name;
recipientCount += 1;
emit RecipientAdded(_fundingAddress, _name);
}

function getCurrentRound() public view returns (FundingRound _currentRound) {
return currentRound;
}
Expand Down
56 changes: 56 additions & 0 deletions contracts/tests/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,62 @@ describe('Funding Round Factory', () => {
// console.log('Approved');
});

describe('adding recipients', () => {
let fundingAddress: string;
let recipientName: string;
beforeEach(() => {
fundingAddress = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045';
recipientName = 'test';
});

it('allows owner to add recipient', async () => {
await expect(factory.addRecipient(fundingAddress, recipientName))
.to.emit(factory, 'RecipientAdded')
.withArgs(fundingAddress, recipientName);
expect(await factory.recipients(fundingAddress))
.to.equal(recipientName);
});

it('rejects calls from anyone except owner', async () => {
const contributorFactory = factory.connect(contributor);
await expect(contributorFactory.addRecipient(fundingAddress, recipientName))
.to.be.revertedWith('Ownable: caller is not the owner');
});

it('should not accept zero-address', async () => {
fundingAddress = '0x0000000000000000000000000000000000000000';
await expect(factory.addRecipient(fundingAddress, recipientName))
.to.be.revertedWith('Factory: Recipient address is zero');
});

it('should not accept empty string as name', async () => {
recipientName = ''
await expect(factory.addRecipient(fundingAddress, recipientName))
.to.be.revertedWith('Factory: Recipient name is empty string');
});

it('should not accept already registered address', async () => {
await factory.addRecipient(fundingAddress, recipientName);
recipientName = 'test-2';
await expect(factory.addRecipient(fundingAddress, recipientName))
.to.be.revertedWith('Factory: Recipient already registered');
});

it('should limit the number of recipients', async () => {
const maxRecipientCount = 16;
for (var i = 0; i < maxRecipientCount + 1; i++) {
recipientName = String(i + 1).padStart(4, '0');
fundingAddress = `0x000000000000000000000000000000000000${recipientName}`;
if (i < maxRecipientCount) {
await factory.addRecipient(fundingAddress, recipientName);
} else {
await expect(factory.addRecipient(fundingAddress, recipientName))
.to.be.revertedWith('Factory: Recipient limit reached');
}
}
});
});

it('has new round running', async () => {
expect(await factory.currentRound()).to.properAddress;
});
Expand Down