diff --git a/lib/config/contracts.js b/lib/config/contracts.js index ef3756a0..aa3bb014 100644 --- a/lib/config/contracts.js +++ b/lib/config/contracts.js @@ -13,6 +13,7 @@ ContractsConfig.prototype.init = function(files) { this.contractDB = {}; this.contractFiles = files; this.contractDependencies = {}; + this.contractStubs = {}; //TODO: have to specify environment otherwise wouldn't work with staging if (this.blockchainConfig.config != undefined) { @@ -38,6 +39,15 @@ ContractsConfig.prototype.config = function(env) { return this.contractConfig[env]; }; +ContractsConfig.prototype.is_a_token = function(target, compiled_contracts) { + for (var className in compiled_contracts) { + if (this.contractStubs[className] && this.contractStubs[className].indexOf(target) >= 0) { + return true; + } + } + return false; +}; + ContractsConfig.prototype.compileContracts = function(env) { var contractFile, source, j; var contractsConfig = this.config(env); @@ -59,6 +69,8 @@ ContractsConfig.prototype.compileContracts = function(env) { this.contractDependencies[className].push(arg.substr(1)); } } + + this.contractStubs[className] = options.stubs; } } @@ -68,10 +80,14 @@ ContractsConfig.prototype.compileContracts = function(env) { contractFile = this.contractFiles[j]; source = fs.readFileSync(contractFile).toString() - console.log("compiling " + contractFile); compiled_contracts = this.compiler.compile(source); - for (className in compiled_contracts) { + for (var className in compiled_contracts) { var contract = compiled_contracts[className]; + + if (this.is_a_token(className, compiled_contracts)) { + continue; + } + all_compiled_contracts[className] = contract; this.all_contracts.push(className); this.contractDB[className] = { diff --git a/test/config.contracts.js b/test/config.contracts.js index cc2150e6..bd4fe135 100644 --- a/test/config.contracts.js +++ b/test/config.contracts.js @@ -91,6 +91,23 @@ describe('embark.config.contracts', function() { }); }); + context("contracts as arguments to other contracts with stubs", function() { + before(function() { + files = [ + 'test/support/contracts/crowdsale.sol', + 'test/support/contracts/token.sol' + ] + contractsConfig = new Config.Contracts(blockchainConfig, compiler); + contractsConfig.loadConfigFile('test/support/arguments2.yml'); + contractsConfig.init(files); + contractsConfig.compileContracts('development'); + }); + + it('add contracts to a list', function() { + assert.deepEqual(contractsConfig.all_contracts, [ "token", "Crowdsale" ]); + }); + }); + }); }); diff --git a/test/deploy.js b/test/deploy.js index de02529b..f605e7d7 100644 --- a/test/deploy.js +++ b/test/deploy.js @@ -66,6 +66,33 @@ describe('embark.deploy', function() { }); }); + describe('contracts as arguments to other contracts with stubs', function() { + var files = [ + 'test/support/contracts/crowdsale.sol', + 'test/support/contracts/token.sol' + ]; + + describe('#deploy_contracts', function() { + var deploy = setDeployConfig({ + files: files, + blockchain: 'test/support/blockchain.yml', + contracts: 'test/support/arguments2.yml' + }); + deploy.deploy_contracts("development"); + + it("should deploy contracts", function() { + var all_contracts = ['token', 'Crowdsale']; + for(var i=0; i < all_contracts.length; i++) { + var className = all_contracts[i]; + + assert.equal(deploy.deployedContracts.hasOwnProperty(className), true); + } + }); + + }); + + }); + describe('contracts instances', function() { var files = [ 'test/support/contracts/simple_storage.sol' diff --git a/test/support/arguments2.yml b/test/support/arguments2.yml new file mode 100644 index 00000000..86765c6b --- /dev/null +++ b/test/support/arguments2.yml @@ -0,0 +1,13 @@ +development: + token: + args: + Crowdsale: + stubs: + - token + args: + - 0x123 + - 100000000000000000000 + - 30 + - 20000000000000000 + - $token +staging: diff --git a/test/support/contracts/crowdsale.sol b/test/support/contracts/crowdsale.sol new file mode 100644 index 00000000..a882dc81 --- /dev/null +++ b/test/support/contracts/crowdsale.sol @@ -0,0 +1,51 @@ +contract token { mapping (address => uint) public coinBalanceOf; function token() {} function sendCoin(address receiver, uint amount) returns(bool sufficient) { } } + +contract Crowdsale { + + address public beneficiary; + uint public fundingGoal; uint public amountRaised; uint public deadline; uint public price; + token public tokenReward; + Funder[] public funders; + event FundTransfer(address backer, uint amount, bool isContribution); + + /* data structure to hold information about campaign contributors */ + struct Funder { + address addr; + uint amount; + } + + /* at initialization, setup the owner */ + function Crowdsale(address _beneficiary, uint _fundingGoal, uint _duration, uint _price, token _reward) { + beneficiary = _beneficiary; + fundingGoal = _fundingGoal; + deadline = now + _duration * 1 minutes; + price = _price; + tokenReward = token(_reward); + } + + /* The function without name is the default function that is called whenever anyone sends funds to a contract */ + function () { + uint amount = msg.value; + funders[funders.length++] = Funder({addr: msg.sender, amount: amount}); + amountRaised += amount; + tokenReward.sendCoin(msg.sender, amount / price); + FundTransfer(msg.sender, amount, true); + } + + modifier afterDeadline() { if (now >= deadline) _ } + + /* checks if the goal or time limit has been reached and ends the campaign */ + function checkGoalReached() afterDeadline { + if (amountRaised >= fundingGoal){ + beneficiary.send(amountRaised); + FundTransfer(beneficiary, amountRaised, false); + } else { + FundTransfer(0, 11, false); + for (uint i = 0; i < funders.length; ++i) { + funders[i].addr.send(funders[i].amount); + FundTransfer(funders[i].addr, funders[i].amount, false); + } + } + suicide(beneficiary); + } +} diff --git a/test/support/contracts/token.sol b/test/support/contracts/token.sol new file mode 100644 index 00000000..fbaa6739 --- /dev/null +++ b/test/support/contracts/token.sol @@ -0,0 +1,18 @@ +contract token { + mapping (address => uint) public coinBalanceOf; + event CoinTransfer(address sender, address receiver, uint amount); + + /* Initializes contract with initial supply tokens to the creator of the contract */ + function token(uint supply) { + coinBalanceOf[msg.sender] = (supply || 10000); + } + + /* Very simple trade function */ + function sendCoin(address receiver, uint amount) returns(bool sufficient) { + if (coinBalanceOf[msg.sender] < amount) return false; + coinBalanceOf[msg.sender] -= amount; + coinBalanceOf[receiver] += amount; + CoinTransfer(msg.sender, receiver, amount); + return true; + } +}