My contract .sol file looks like this:
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import "#openzeppelin/contracts/token/ERC777/ERC777.sol";
contract ERC777MainToken is ERC777{
constructor(address[] memory defaultOperators) ERC777("COIN", "COIN", defaultOperators) { }
}
And the migration looks like this:
const ERC777MainToken = artifacts.require("ERC777MainToken");
module.exports = async function(_deployer) {
const mainToken = await _deployer.deploy(ERC777MainToken, ["0x5d95F05Dd72A5cB9ea2ee2DC271B03A41C933Cad"])
};
On truffle migrate I get the following error:
"ERC777MainToken" hit a require or revert statement somewhere in its constructor. Try:
* Verifying that your constructor params satisfy all require conditions.
* Adding reason strings to your require statements.
at /usr/local/lib/node_modules/truffle/build/webpack:/packages/deployer/src/deployment.js:365:1
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at Migration._deploy (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/Migration.js:74:1)
at Migration._load (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/Migration.js:61:1)
at Migration.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/Migration.js:212:1)
at Object.runMigrations (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:150:1)
at Object.runFrom (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:110:1)
at Object.runAll (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:114:1)
at Object.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/migrate/index.js:79:1)
at runMigrations (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/commands/migrate.js:263:1)
at Object.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/commands/migrate.js:228:1)
at Command.run (/usr/local/lib/node_modules/truffle/build/webpack:/packages/core/lib/command.js:136:1)
Any Ideas why? I have check every constructor and no one has any require conditions.
I find the problem. The ERC777 contract from open zeppelin has an hardcoded memeber _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24) which is the global ERC1820 Registry for the main net but since I am on local net this address is at most nothing.
contract ERC777 is Context, IERC777, IERC20 {
using Address for address;
IERC1820Registry constant internal _ERC1820_REGISTRY = IERC1820Registry(0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24);
mapping(address => uint256) private _balances;
....
}
And the constructor is tring to access the contract on this address:
constructor(
string memory name_,
string memory symbol_,
address[] memory defaultOperators_
) {
_name = name_;
_symbol = symbol_;
_defaultOperatorsArray = defaultOperators_;
for (uint256 i = 0; i < defaultOperators_.length; i++) {
_defaultOperators[defaultOperators_[i]] = true;
}
// register interfaces
_ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC777Token"), address(this));
_ERC1820_REGISTRY.setInterfaceImplementer(address(this), keccak256("ERC20Token"), address(this));
}
But since this address on the local net might be empty and 100% is not what it should be the transaction is reverted.
If in your code you have a require or revert statement in your contract, add an error message like this: require(condition, errorMessage); or revert (errorMessage);
Related
Given Solidity ^0.8.13 file X.sol, contains an interface of contract Y and contract X
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface YI{
// This is the interface of contract Y
function hello() external payable;
}
contract X{
YI public targetContract;
constructor(address _target) {
targetContract = YI(_target);
}
}
and the compile code:
from web3 import Web3
import solcx # type: ignore
from typing import Any
# run the line below to install the compiler -> only once is needed.
# solcx.install_solc(version='latest')
def _compile(file_name: str) -> Any:
# set the version
solcx.set_solc_version('0.8.13')
# compile
compiled_sol = solcx.compile_files(
[file_name], output_values=['abi', 'bin'])
# retrieve the contract interface
contract_id, contract_interface = compiled_sol.popitem()
return contract_interface['bin'], contract_interface['abi']
bytecode, abi = _compile("X.sol")
the bytecode returns as empty string instead of bytes, any hint what am I missing?
I use python py-solc-x
I'm writing a Solidity smartcontract.
Working on Kovan testnet.
I understood from the Uniswap documentation, that the .pairFor method from the uniswapV2Library contract should return an address for this pair of tokens.
For free, since it's not making external calls, it's calculating inside.
And that .getPair method on the uniswapV2Factory should do the same, but via a request that costs gas.
However, both methods return a different address, and I can't understand how that is possible.
Can somebody explain what I'm missing?
This is my contract (i simplified it a bit), most important is the repl function:
pragma solidity =0.8.12;
import './UniswapV2Library.sol';
import './interfaces/IUniswapV2Router02.sol';
import './interfaces/IUniswapV2Pair.sol';
import './interfaces/IUniswapV2Factory.sol';
contract FlashLoaner {
address immutable factory;
IUniswapV2Router02 immutable sushiRouter;
IUniswapV2Factory immutable factoryV2;
address public var1;
address public var2;
address public resultPair;
address public resPair2;
address public fact;
constructor(address _factory, address _uniRouter, address _sushiRouter) public {
factory = _factory;
sushiRouter = IUniswapV2Router02(_sushiRouter);
factoryV2 = IUniswapV2Factory(0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f);
}
function repl(address _sender, uint _amount0, uint _amount1) external {
//0x052AE8b0F7E5c610937920e46ED265c2063Cb7B8 = uniswapV2pair WETH RAI
address msgsender = 0x052AE8b0F7E5c610937920e46ED265c2063Cb7B8;
IUniswapV2Pair v2Pair = IUniswapV2Pair(msgsender);
address token0 = v2Pair.token0();
address token1 = v2Pair.token1();
//uniswap v2 factory address
fact = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
//results in 0x3c8B7Cf2bDCC9DEB44a72f40052ae8b0F7E5C610
//which i don't understand??
resultPair = UniswapV2Library.pairFor(fact, token1, token0);
//results in 0x052AE8b0F7E5c610937920e46ED265c2063Cb7B8 = uniswapV2pair WETH RAI
//which makes total sense
resPair2 = factoryV2.getPair(token0, token1);
}
}
Why is resPair2 not the same as resultPair??
I'm new to solidity. I'm currently getting the following error TransferHelper: TRANSFER_FROM_FAILED from the safeTransferFrom function. Can someone tell me why?
What is this line doing?
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(0x23b872dd, from, to, value)
);
Here's the entire contract:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
/**
* #dev A helper methods for interacting with ERC20 tokens and
sending ETH that do not consistently return true/false.
*/
library TransferHelper {
function safeApprove(
address token,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(0x095ea7b3, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper: APPROVE_FAILED"
);
}
function safeTransfer(
address token,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(0xa9059cbb, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper: TRANSFER_FAILED"
);
}
function safeTransferFrom(
address token,
address from,
address to,
uint256 value
) internal {
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(0x23b872dd, from, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TransferHelper: TRANSFER_FROM_FAILED"
);
}
function safeTransferETH(address to, uint256 value) internal {
(bool success, ) = to.call{value: value}(new bytes(0));
require(success, "TransferHelper: ETH_TRANSFER_FAILED");
}
}
Just a note, TransferHelper is the prewritten library, and we shouldn't touch into it. What you should do is see the message like: Transfer From Failed or approved fail and check our ERC20 token code as well as the data submit whether it's valid or not.
1st question:
This problem usually happens when your ERC20 token can't be transfer.
There're several reason for this: un-approval, not enough balance...
2nd question:
abi.encodeWithSelector(0x23b872dd, from, to, value)
This function returns a selector (think of is as a function ref) to the transfer(...) of your ERC20 token. And this is called by token.call( a kind of reflection.
This error is for the following reasons:
if the token has fees on transfer remember to be correctly calling the exchange function that supports transfer fees: https://docs.uniswap.org/protocol/V2/reference/smart-contracts/router-02
note that the token submissions permission is sufficient in the token contract. The same happens with the manipulation of WETH it is necessary to give the necessary permissions in the contract.
I am having issues when trying to use the Chainlink random number generator and deploying to Rinkeby. Relevant code pieces are the following:
Constructor from the importing contract (should be working fine).
// RandomNumberConsumer parameters for RINKEBY testnet
address _vrfCoordinator = 0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B;
address _link = 0x01BE23585060835E02B77ef475b0Cc51aA1e0709;
bytes32 _keyHash = 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311;
uint256 _fee = 0.1 * 10 ** 18; // 0.1 LINK
constructor() RandomNumberConsumer(_vrfCoordinator, _link, _keyHash, _fee) {}
RandomNumberConsumer.sol. As specified in the chainlink docs, with a few tweaks needed for my approach.
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "hardhat/console.sol";
contract RandomNumberConsumer is VRFConsumerBase, Ownable{
// Variables
bytes32 internal s_keyHash;
uint256 internal s_fee;
uint256 private constant ROLL_IN_PROGRESS = 150;
mapping(bytes32 => address) private s_rollers;
mapping(address => uint256) private s_results;
//address vrfCoordinator = 0x3d2341ADb2D31f1c5530cDC622016af293177AE0;
//address link = 0xb0897686c545045aFc77CF20eC7A532E3120E0F1;
// Events
event DiceRolled(bytes32 indexed requestId, address indexed roller);
event DiceLanded(bytes32 indexed requestId, uint256 indexed result);
/**
* Constructor inherits VRFConsumerBase
*
* Network: Rinkeby
* Chainlink VRF Coordinator address: 0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B
* LINK token address: 0x01BE23585060835E02B77ef475b0Cc51aA1e0709
* Key Hash: 0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311
*/
constructor(address vrfCoordinator, address link, bytes32 keyHash, uint256 fee)
VRFConsumerBase(vrfCoordinator, link){
s_keyHash = keyHash;
s_fee = fee;
}
// Functions
function rollDice(address roller) public onlyOwner returns (bytes32 requestId){
console.log("RNG Contract address",address(this));
// Checking LINK balance
require(LINK.balanceOf(address(this)) >= s_fee, "Not enough LINK in contract.");
// Checking if roller has already rolled dice since each roller can only ever be assigned to a single house. TODO: this can be changed
require(s_results[roller] == 0, "Already rolled");
// Requesting randomness
requestId = requestRandomness(s_keyHash, s_fee); // Error is happening here!
// Storing requestId and roller address
s_rollers[requestId] = roller;
// Emitting event to signal rolling of dice
s_results[roller] = ROLL_IN_PROGRESS;
emit DiceRolled(requestId, roller);
}
// fulfillRandomness is a special function defined within the VRFConsumerBase contract that our contract extends from.
// The coordinator sends the result of our generated randomness back to fulfillRandomness.
function fulfillRandomness(bytes32 requestId, uint256 randomness) override internal {
// Transform the result to a number between 0 and 100, both included. Using % as modulo
require(randomness!=0, "Modulo zero!");
uint256 d100Value = (randomness % 100) + 1; // +1 so s_results[player] can be 0 if no dice has been rolled
// Assign the transformed value to the address in the s_results mapping variable.
s_results[s_rollers[requestId]] = d100Value;
// Emit a DiceLanded event.
emit DiceLanded(requestId, d100Value);
}
// playerWins determines whether the player wins or lose the battle, based on a fixed chance (0-100)
function playerWins (address player, uint8 chance) internal view returns (bool wins){
require(s_results[player] != 0, "Player has not engaged in battle!");
require(s_results[player] != ROLL_IN_PROGRESS, "Battle in progress!");
return s_results[player] <= (chance + 1); //+1 because dice is 1-101
}
}
RNG call from the importing contract(simplified to relevant part only. _player address is working correctly).
address _player = ownerOf(_monId);
rollDice(_player);
I have the certainty that the error occurs inside the rollDice function, more specifically in the call to requestRandomness. Apart from that, I cannot seem to find why the error is hapenning, nor any references to the error message (Below agreed payment) inside any of the dependency contracts. Cannot find any references online either.
Any help is appreciated, thanks.
Below agreed payment error message comes from the sufficientLINK modifier of the VRFCoordinator.sol contract. You can see it here and here.
Double-check the constructor parameters, especially the fee value.
Also, make sure to fund your smart contract with Rinkeby LINK tokens which you can claim from the faucet.
suppose I have this solidity contract, I would like to calculate the result of minAmountOut2, without actually paying the gas gas fee. Is it possible to achieve it? I think this should be theoretically possible, but I'm not sure how to achieve it practically.... Thanks!
pragma solidity >=0.7.0 <0.9.0;
contract Storage {
constructor() payable {
// uint256 number;
address wbnb_addres = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
address pancake_swap_v2 = 0x10ED43C718714eb63d5aA57B78B54704E256024E;
uint amount = msg.value ;
address target_token_address = 0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82;
address sender_address = tx.origin;
address[] memory address_input = new address[](2);
address_input[0] = wbnb_addres;
address_input[1] = target_token_address;
uint[] memory result = IPancakeRouter02(pancake_swap_v2).getAmountsOut(amount,address_input);
uint minAmountOut = result[1];
uint deadline = 1e30;
address[] memory address_output2 = new address[](2);
address_output2[0] = target_token_address;
address_output2[1] = wbnb_addres;
uint[] memory result2 = IPancakeRouter02(pancake_swap_v2).getAmountsOut(minAmountOut,address_output2);
uint minAmountOut2 = result2[1];
}
}
One possible way is that I convert the result into string and trigger a revert function.... Then when I run estimatgas function in web3, then i got the result using error and exception handling.
Far as I know estimateGas is the only such function. estimateGas should be almost equal to web3.eth.sendTransaction, the only difference between them is estimateGas does not send the transaction out actually, and if your operation will fail when call a function, you can not get a valid result by estimateGas.
You have now all code in constructor. You probably want to split the code up in smaller functions and then call estimateGas.