Skip to content

Commit

Permalink
refundable crowdsale
Browse files Browse the repository at this point in the history
  • Loading branch information
tiero committed Oct 15, 2017
1 parent 3867f64 commit bd095c0
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 5 deletions.
14 changes: 9 additions & 5 deletions dao/py/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,18 @@ def parseAbi(data):
agentRegistryAbi = parseAbi(json.loads(open('../build/contracts/AgentRegistry.json','r').read()))
agentFactoryAbi = parseAbi(json.loads(open('../build/contracts/AgentFactory.json','r').read()))
agentAbi = parseAbi(json.loads(open('../build/contracts/Agent.json','r').read()))
crowdsaleAbi = parseAbi(json.loads(open('../build/contracts/AgiCrowdsale.json','r').read()))
#addresses
agentRegistryAddress = getAddressByName(json.loads(open('../addresses.json','r').read()),'AgentRegistry')
agentFactoryAddress = getAddressByName(json.loads(open('../addresses.json','r').read()),'AgentFactory')
agentAddress = getAddressByName(json.loads(open('../addresses.json','r').read()),'Agent')

crowdsaleAddress = getAddressByName(json.loads(open('../addresses.json','r').read()),'AgiCrowdsale')

#Contracts
agentRegistryContract = web3.eth.contract(abi = agentRegistryAbi, address=agentRegistryAddress)
agentFactoryContract = web3.eth.contract(abi = agentFactoryAbi, address=agentFactoryAddress)
agentContract = web3.eth.contract(abi = agentAbi, address=agentAddress)
crowdsaleContract = web3.eth.contract(abi = crowdsaleAbi, address=crowdsaleAddress, args)


def joinNetwork():
Expand All @@ -84,16 +86,18 @@ def findServiceProviders(service):
def getAgentsById(id):
return agentRegistryContract.call(payload).getAgent(id)


# assign an integer for each service
# wordSenseDisambiguation = 0,
# textSummarization = 1



# Here I'm joining the network and putting in myself the address on the blockchain
myself1 = joinNetwork()
print("myself_1 {0}".format(myself1))
myself2 = joinNetwork()
print("myself_2 {0}".format(myself2))
#myself1 = joinNetwork()
#print("myself_1 {0}".format(myself1))
#myself2 = joinNetwork()
#print("myself_2 {0}".format(myself2))

#test_agent = newAgent()
#print("test_agent {0}".format(test_agent))
Expand Down
79 changes: 79 additions & 0 deletions dao/test/TestAgiCrowdsale.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
const RefundableCrowdsale = artifacts.require('AgiCrowdsale.sol')
const MintableToken = artifacts.require('MintableToken')

const ether = require('./helpers/ether')
const { advanceBlock } = require('./helpers/advanceToBlock')
const { increaseTimeTo, duration } = require('./helpers/increaseTime')
const latestTime = require('./helpers/latestTime')
const EVMThrow = 'Invalid opcode'

const BigNumber = web3.BigNumber

contract('AgiCrowdsale', function ([_, owner, wallet, investor]) {

const rate = new BigNumber(1000)
const goal = ether(800)
const lessThanGoal = ether(750)

before(async function () {
//Advance to the next block to correctly read time in the solidity "now" function interpreted by testrpc
await advanceBlock()
})

beforeEach(async function () {
this.startTime = latestTime() + duration.weeks(1)
this.endTime = this.startTime + duration.weeks(1)
this.afterEndTime = this.endTime + duration.seconds(1)

this.crowdsale = await RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, goal, { from: owner })
})

describe('creating a valid crowdsale', function () {

it('should fail with zero goal', async function () {
await RefundableCrowdsale.new(this.startTime, this.endTime, rate, wallet, 0, { from: owner }).should.be.rejectedWith(EVMThrow);
})

});

it('should deny refunds before end', async function () {
await this.crowdsale.claimRefund({ from: investor }).should.be.rejectedWith(EVMThrow)
await increaseTimeTo(this.startTime)
await this.crowdsale.claimRefund({ from: investor }).should.be.rejectedWith(EVMThrow)
})

it('should deny refunds after end if goal was reached', async function () {
await increaseTimeTo(this.startTime)
await this.crowdsale.sendTransaction({ value: goal, from: investor })
await increaseTimeTo(this.afterEndTime)
await this.crowdsale.claimRefund({ from: investor }).should.be.rejectedWith(EVMThrow)
})

it('should allow refunds after end if goal was not reached', async function () {
await increaseTimeTo(this.startTime)
await this.crowdsale.sendTransaction({ value: lessThanGoal, from: investor })
await increaseTimeTo(this.afterEndTime)

await this.crowdsale.finalize({ from: owner })

const pre = web3.eth.getBalance(investor)
await this.crowdsale.claimRefund({ from: investor, gasPrice: 0 })
.should.be.fulfilled
const post = web3.eth.getBalance(investor)

post.minus(pre).should.be.bignumber.equal(lessThanGoal)
})

it('should forward funds to wallet after end if goal was reached', async function () {
await increaseTimeTo(this.startTime)
await this.crowdsale.sendTransaction({ value: goal, from: investor })
await increaseTimeTo(this.afterEndTime)

const pre = web3.eth.getBalance(wallet)
await this.crowdsale.finalize({ from: owner })
const post = web3.eth.getBalance(wallet)

post.minus(pre).should.be.bignumber.equal(goal)
})

})
22 changes: 22 additions & 0 deletions dao/test/helpers/advanceToBlock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
exports.advanceBlock = function() {
return new Promise((resolve, reject) => {
web3.currentProvider.sendAsync({
jsonrpc: '2.0',
method: 'evm_mine',
id: Date.now(),
}, (err, res) => {
return err ? reject(err) : resolve(res)
})
})
}

// Advances the block number so that the last mined block is `number`.
exports.advanceToBlock = async function(number) {
if (web3.eth.blockNumber > number) {
throw Error(`block number ${number} is in the past (current is ${web3.eth.blockNumber})`)
}

while (web3.eth.blockNumber < number) {
await advanceBlock()
}
}
3 changes: 3 additions & 0 deletions dao/test/helpers/ether.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = function(n) {
return new web3.BigNumber(web3.toWei(n, 'ether'))
}
48 changes: 48 additions & 0 deletions dao/test/helpers/increaseTime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
const latestTime = require('./latestTime')

// Increases testrpc time by the passed duration in seconds
exports.increaseTime = function(duration) {
const id = Date.now()

return new Promise((resolve, reject) => {
web3.currentProvider.sendAsync({
jsonrpc: '2.0',
method: 'evm_increaseTime',
params: [duration],
id: id,
}, err1 => {
if (err1) return reject(err1)

web3.currentProvider.sendAsync({
jsonrpc: '2.0',
method: 'evm_mine',
id: id+1,
}, (err2, res) => {
return err2 ? reject(err2) : resolve(res)
})
})
})
}

/**
* Beware that due to the need of calling two separate testrpc methods and rpc calls overhead
* it's hard to increase time precisely to a target point so design your test to tolerate
* small fluctuations from time to time.
*
* @param target time in seconds
*/
exports.increaseTimeTo = function(target) {
let now = latestTime();
if (target < now) throw Error(`Cannot increase current time(${now}) to a moment in the past(${target})`);
let diff = target - now;
return increaseTime(diff);
}

exports.duration = {
seconds: function(val) { return val},
minutes: function(val) { return val * this.seconds(60) },
hours: function(val) { return val * this.minutes(60) },
days: function(val) { return val * this.hours(24) },
weeks: function(val) { return val * this.days(7) },
years: function(val) { return val * this.days(365)}
};
4 changes: 4 additions & 0 deletions dao/test/helpers/latestTime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Returns the time of the last mined block in seconds
module.exports = function() {
return web3.eth.getBlock('latest').timestamp;
}

0 comments on commit bd095c0

Please sign in to comment.