Estoy probando un contrato ERC20 basado en la plantilla de solidez de Openzeppelin. Pero estoy observando un comportamiento curioso al leer una variable global. Aquí está el contrato:
pragma solidity ^0.4.24;
import "../node_modules/openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
contract FunnyToken is ERC20 {
string public constant name = "FunnyToken";
string public constant symbol = "FYT";
uint8 public constant decimals = 18;
uint256 private _totalSupply = 10000 * (10 ** uint256(decimals));
address private owner;
constructor() public {
owner = msg.sender;
}
}
luego truffle migrate
lo conecto a ganache-cli y ejecuto los siguientes comandos en la consola de truffle:
FunnyToken.deployed().then(inst=> tok=inst);
tok.totalSupply();
el valor devuelto es: BigNumber { s: 1, e: 0, c: [ 0 ] }
. Entonces concluyo que la variable global _totalSupply no se está inicializando correctamente, porque la función totalSupply
se implementa así:
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
¿Alguien puede explicarme qué está pasando?
El problema es que está creando una nueva variable de almacenamiento en su FunnyToken
contrato. El contrato base seguirá accediendo a la antigua variable de almacenamiento.
Una solución es asignar el valor en el constructor.
pragma solidity ^0.4.0;
contract TokenBase {
uint _totalSupply;
function totalSupply() public view returns (uint) {
return _totalSupply;
}
}
contract Token is TokenBase {
// uint _totalSupply = 4321; // <-- this creates a new storage variable
constructor() public {
_totalSupply = 1234; // It is better to initialize the old variable
}
}
Otra solución posible es anular la función totalSupply()
de su contrato, pero desperdiciará un espacio adicional de almacenamiento.
_mint
.Todo lo que necesita hacer es convertir el número grande en un número real. Además, teniendo en cuenta cuántas personas usan zepelín abierto, parece bastante inusual que esto suceda. Intente mostrar el gran número como un número.
const number = tok.totalSupply()
number.toNumber()
Consulte ¿Cómo convertir BigNumber a Number en el marco de Truffle?
Encontré la respuesta a mi propia pregunta: tras la herencia, los contratos derivados no pueden acceder a las variables privadas del contrato base (gracioso, pero cierto), por lo tanto, cuando llamo totalSupply
(definido el contrato base) accederá _totalSupply
desde el contrato base, en lugar de el que definí en el contrato derivado, devolviendo así 0.
Supongo que para solucionar esto tendría que sobrecargar el totalSupply
método en el contrato derivado. Eso sí no lo he probado.
Usted declaró _totalSupply como
uint256 private _totalSupply = 10000 * (10 ** uint256(decimals));
Dado que es una variable privada dentro de su contrato base, no podrá llamarla desde ninguno de sus contratos derivados ( Motivo ).
Ahora, es aún más sencillo omitir lo mismo en Solidity ^0.5.0:
pragma solidity ^0.5.0;
import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Full.sol';
import 'openzeppelin-solidity/contracts/token/ERC721/ERC721Mintable.sol';
contract FunnyToken is ERC20 {
string public constant name = "FunnyToken";
string public constant symbol = "FYT";
uint8 public constant decimals = 18;
uint256 public _totalSupply = 10000;
address private owner;
constructor() public {
owner = msg.sender;
}
}
Espero tener claro lo anterior. Gracias
maxpeinas
totalSupply
?