Estoy probando un contrato Crowdsale (C) que envía tokens de un contrato ya implementado (T). La idea es enviar una cantidad de tokens a C desde T, y luego venderlos por Ether, pero nada funciona, C ni siquiera recibe el Ether. Aquí está el contrato de Crowdsale:
pragma solidity ^0.4.13;
contract ForeignToken {
function balanceOf(address _owner) constant returns (uint256);
function transfer(address _to, uint256 _value) returns (bool);
}
library SafeMath {
function mul(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal constant returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract Token {
function issue(address _recipient, uint256 _value) returns (bool success);
function totalSupply() constant returns (uint256 supply);
function unlock() returns (bool success);
}
contract TokenCrowdsale {
using SafeMath for uint256;
// Crowdsale details
address public beneficiary;
address public creator;
address public confirmedBy;
uint256 public maxSupply = 15000000e8;
uint256 public minAcceptedAmount = 10 finney;
bool public purchasingAllowed = false;
// Eth to token rate
uint256 public rate = 2000;
enum Stages {
PreSale,
InProgress,
Ended,
Withdrawn
}
Stages public stage = Stages.PreSale;
// deployed token
Token public deplToken;
// Invested balances
mapping (address => uint256) balances;
/**
* Throw if at stage other than current stage
*
* @param _stage expected stage to test for
*/
modifier atStage(Stages _stage) {
require(stage == _stage);
_;
}
/**
* Throw if sender is not beneficiary
*/
modifier onlyBeneficiary() {
require(beneficiary == msg.sender);
_;
}
/**
* Get balance of `_investor`
*
* @param _investor The address from which the balance will be retrieved
* @return The balance
*/
function balanceOf(address _investor) constant returns (uint256 balance) {
return balances[_investor];
}
function enablePurchasing() onlyBeneficiary atStage(Stages.PreSale) {
purchasingAllowed = true;
stage = Stages.InProgress;
}
function disablePurchasing() onlyBeneficiary atStage(Stages.InProgress) {
purchasingAllowed = false;
stage = Stages.Ended;
}
function enableNewPurchasing() onlyBeneficiary atStage(Stages.Withdrawn) {
purchasingAllowed = true;
stage = Stages.InProgress;
}
/**
* Constructor
*
* @param _tokenAddress The address of the token contact
* @param _beneficiary The address of the wallet for the beneficiary
* @param _creator The address of the wallet for the creator
*/
function TokenCrowdsale(address _tokenAddress, address _beneficiary, address _creator) {
deplToken = Token(_tokenAddress);
beneficiary = _beneficiary;
creator = _creator;
}
/**
* For testing purposes
*
* @return The beneficiary address
*/
function confirmBeneficiary() onlyBeneficiary {
confirmedBy = msg.sender;
}
/**
* Transfer raised amount to the beneficiary address
*/
function withdraw() onlyBeneficiary atStage(Stages.Ended) {
uint256 ethBalance = this.balance;
beneficiary.transfer(ethBalance);
stage = Stages.Withdrawn;
}
/**
* Receives Eth and issue tokens to the sender
*/
function () payable atStage(Stages.InProgress) {
require(purchasingAllowed);
address investor = msg.sender;
uint256 received = (msg.value).div(10e8);
// Enforce min amount
require(received >= minAcceptedAmount);
uint256 tokens = (received).mul(rate);
require(tokens > 0);
require(deplToken.issue(investor, tokens));
balances[investor] = balances[investor].add(received);
//raised += received;
// Check totalSupply raised
if (deplToken.totalSupply() >= maxSupply) {
stage = Stages.Ended;
}
}
function withdrawForeignTokens(address _tokenContract) onlyBeneficiary public returns (bool) {
ForeignToken token = ForeignToken(_tokenContract);
uint256 amount = token.balanceOf(address(this));
return token.transfer(beneficiary, amount);
}
}
Cualquier ayuda se agradece, gracias
EDITAR: después de las sugerencias en los comentarios, logré recibir ETH en el contrato de Crowdsale, pero no está emitiendo los tokens. Aquí está el código:
pragma solidity ^0.4.13;
contract ForeignToken {
function balanceOf(address _owner) constant returns (uint256);
function transfer(address _to, uint256 _value) returns (bool);
}
library SafeMath {
function mul(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal constant returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
contract Token {
function issue(address _recipient, uint256 _value) returns (bool success);
function totalSupply() constant returns (uint256 supply);
function unlock() returns (bool success);
}
contract TokenCrowdsale {
using SafeMath for uint256;
// Crowdsale details
address public beneficiary;
address public creator;
address public confirmedBy;
uint256 public maxSupply = 15000000e8;
uint256 public minAcceptedAmount = 10 finney;
bool public purchasingAllowed = false;
uint256 public totalSupply = 0;
// Eth to token rate
uint256 public rate = 2000;
enum Stages {
PreSale,
InProgress,
Ended,
Withdrawn
}
Stages public stage = Stages.PreSale;
// deployed token
Token public deplToken;
// Invested balances
mapping (address => uint256) balances;
/**
* Throw if at stage other than current stage
*
* @param _stage expected stage to test for
*/
modifier atStage(Stages _stage) {
require(stage == _stage);
_;
}
/**
* Throw if sender is not beneficiary
*/
modifier onlyBeneficiary() {
require(beneficiary == msg.sender);
_;
}
/**
* Get balance of `_investor`
*
* @param _investor The address from which the balance will be retrieved
* @return The balance
*/
function balanceOf(address _investor) constant returns (uint256 balance) {
return balances[_investor];
}
function enablePurchasing() onlyBeneficiary atStage(Stages.PreSale) {
purchasingAllowed = true;
stage = Stages.InProgress;
}
function disablePurchasing() onlyBeneficiary atStage(Stages.InProgress) {
purchasingAllowed = false;
stage = Stages.Ended;
}
function enableNewPurchasing() onlyBeneficiary atStage(Stages.Withdrawn) {
purchasingAllowed = true;
stage = Stages.InProgress;
}
/**
* Constructor
*
* @param _tokenAddress The address of the token contact
* @param _beneficiary The address of the wallet for the beneficiary
* @param _creator The address of the wallet for the creator
*/
function TokenCrowdsale(address _tokenAddress, address _beneficiary, address _creator) {
deplToken = Token(_tokenAddress);
beneficiary = _beneficiary;
creator = _creator;
}
/**
* For testing purposes
*
* @return The beneficiary address
*/
function confirmBeneficiary() onlyBeneficiary {
confirmedBy = msg.sender;
}
/**
* Transfer raised amount to the beneficiary address
*/
function withdraw() onlyBeneficiary atStage(Stages.Ended) {
uint256 ethBalance = this.balance;
beneficiary.transfer(ethBalance);
stage = Stages.Withdrawn;
}
/**
* Receives Eth and issue tokens to the sender
*/
function () payable atStage(Stages.InProgress) {
require(purchasingAllowed);
if (msg.value >= 10 finney) {
address investor = msg.sender;
uint256 received = (msg.value).div(10e8);
uint256 tokens = (received).mul(rate);
balances[investor] = balances[investor].add(tokens);
totalSupply = (totalSupply).add(tokens);
}
if (totalSupply >= maxSupply) {
purchasingAllowed = false;
stage = Stages.Ended;
}
}
function withdrawForeignTokens(address _tokenContract) onlyBeneficiary public returns (bool) {
ForeignToken token = ForeignToken(_tokenContract);
uint256 amount = token.balanceOf(address(this));
return token.transfer(beneficiary, amount);
}
}
Como puede ver, cambié el "requerir" en la función alternativa con una iteración "si"
Seguir las sugerencias e investigar más me llevó a encontrar la solución. Primero cambié el
contract Token {}
a
interface Token {}
También agregué un evento que luego llama la función de respaldo para enviar tokens:
event sendTokens(address indexed to, uint256 value);
Finalmente, limpié el código de variable no utilizada y agregué alguna otra función no relacionada con mi problema, pero útil para administrar el crowdsale. Aquí está el código de trabajo final:
pragma solidity ^0.4.13;
contract ForeignToken {
function balanceOf(address _owner) constant returns (uint256);
function transfer(address _to, uint256 _value) returns (bool);
}
library SafeMath {
function mul(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal constant returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal constant returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
interface Token {
function transfer(address _to, uint256 _value) returns (bool);
function totalSupply() constant returns (uint256 supply);
function balanceOf(address _owner) constant returns (uint256 balance);
}
contract TokenCrowdsale {
using SafeMath for uint256;
// Crowdsale details
address public beneficiary;
address public creator;
address public confirmedBy;
uint256 public maxSupply = 15000000e8;
bool public purchasingAllowed = false;
uint256 public totalSupplied = 0;
// Eth to token rate
uint256 public rate = 2000;
enum Stages {
PreSale, //0
InProgress, //1
Ended, //2
Withdrawn //3
}
Stages public stage = Stages.PreSale;
// deployed token
Token public deplToken;
// Invested balances
mapping (address => uint256) balances;
/**
* Throw if at stage other than current stage
*
* @param _stage expected stage to test for
*/
modifier atStage(Stages _stage) {
require(stage == _stage);
_;
}
/**
* Throw if sender is not beneficiary
*/
modifier onlyBeneficiary() {
require(beneficiary == msg.sender);
_;
}
/**
* Get balance of `_investor`
*
* @param _investor The address from which the balance will be retrieved
* @return The balance
*/
function balanceOf(address _investor) constant returns (uint256 balance) {
return balances[_investor];
}
function enablePurchasing() onlyBeneficiary atStage(Stages.PreSale) {
purchasingAllowed = true;
stage = Stages.InProgress;
}
function disablePurchasing() onlyBeneficiary atStage(Stages.InProgress) {
purchasingAllowed = false;
stage = Stages.Ended;
}
function enableNewPurchasing() onlyBeneficiary atStage(Stages.Withdrawn) {
purchasingAllowed = true;
stage = Stages.InProgress;
}
/**
* Constructor
*
* @param _tokenAddress The address of the token contact
* @param _beneficiary The address of the wallet for the beneficiary
* @param _creator The address of the wallet for the creator
*/
function TokenCrowdsale(address _tokenAddress, address _beneficiary, address _creator) {
deplToken = Token(_tokenAddress);
beneficiary = _beneficiary;
creator = _creator;
}
/**
* For testing purposes
*
* @return The beneficiary address
*/
function confirmBeneficiary() onlyBeneficiary {
confirmedBy = msg.sender;
}
event sendTokens(address indexed to, uint256 value);
/**
* Transfer raised amount to the beneficiary address
*/
function withdraw() onlyBeneficiary atStage(Stages.Ended) {
uint256 ethBalance = this.balance;
beneficiary.transfer(ethBalance);
stage = Stages.Withdrawn;
}
/**
* Receives Eth and issue tokens to the sender
*/
function () payable atStage(Stages.InProgress) {
require(purchasingAllowed);
if (msg.value == 0) { return; }
uint256 weiAmount = msg.value;
address investor = msg.sender;
uint256 received = weiAmount.div(10e7);
uint256 tokens = (received).mul(rate);
if (msg.value >= 10 finney) {
uint256 bonusToken = (tokens.div(100)).mul(20);
tokens = tokens.add(bonusToken);
}
sendTokens(msg.sender, tokens);
deplToken.transfer(investor, tokens);
totalSupplied = (totalSupplied).add(tokens);
if (totalSupplied >= maxSupply) {
purchasingAllowed = false;
stage = Stages.Ended;
}
}
function tokensAvailable() constant returns (uint256) {
return deplToken.balanceOf(this);
}
function withdrawForeignTokens(address _tokenContract) onlyBeneficiary public returns (bool) {
ForeignToken token = ForeignToken(_tokenContract);
uint256 amount = token.balanceOf(address(this));
return token.transfer(beneficiary, amount);
}
}
No estoy seguro de si "token de interfaz" o "tokens de envío de eventos", o ambos juntos, fueron las soluciones, pero ahora está funcionando; Puedo enviar ether y recibir el token desplegado. Respondí mi propia pregunta, por lo que permanecerá aquí como una solución si alguien más necesita algo como esto. Gracias
Iteración 122442
crissi mariam robert
usuario19489
Luis Soares
fuddToken
no existeusuario19489
deplToken
, ya que pegué aquí un código antiguo. corregido ahorausuario19489
Luis Soares
Luis Soares
usuario19489
usuario19489