I'm trying to call the getNames() function on the reverse-record ens lookup contract here, but it's reverting. This is my code:
pragma solidity ^0.8.0; pragma experimental ABIEncoderV2;
contract ENStest {
/* ENS Reverse Lookup
Ropsten: 0x72c33B247e62d0f1927E8d325d0358b8f9971C68
Rinkeby: 0x196eC7109e127A353B709a20da25052617295F6f
Goerli: 0x333Fc8f550043f239a2CF79aEd5e9cF4A20Eb41e
Mainnet: 0x3671aE578E63FdF66ad4F3E12CC0c0d71Ac7510C
*/
address public ENSReverseLookupContractAddr = address(0x196eC7109e127A353B709a20da25052617295F6f); // Rinkeby
function addrToENS(address addr) public view returns(string[] memory) {
ReverseRecords ens = ReverseRecords(ENSReverseLookupContractAddr);
return ens.getNames([addr]);
}
}
// ENS Reverse Lookup Remote Contract
abstract contract ReverseRecords {
function getNames(address[] calldata addresses) external view virtual returns (string[] memory r);
}
Anyone know what I'm doing wrong here?
Resolved
I was casting a fixed-length array to a dynamic-sized array.
(h/t https://ethereum.stackexchange.com/a/103894/25695)
Revised code:
function addrToENS(address addr) public view returns(string[] memory) {
ReverseRecords ens = ReverseRecords(ENSReverseLookupContractAddr);
address[] memory t = new address[](1);
t[0] = addr;
return ens.getNames(t);
}
Related
I am creating an NFT collection, and am testing on ropsten. I have my NFT metadata on my website for example boredApes.com/tokens/3.json but the issue is the contract goes to boredApes.com/tokens/3 and not the .json part. How should I change to contract to load this metadata. The current solidity function is
function _baseURI() internal pure override returns (string memory) { return "https://boredApes.com/tokens/"; }
The _baseURI() function sets just the beginning of the URI. You need to override the tokenURI() function as well, appending the .json string at the end of the returned URI.
pragma solidity ^0.8;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721.sol";
contract MyCollection is ERC721 {
constructor() ERC721("MyCollection", "MyC") {
_mint(msg.sender, 1);
}
function _baseURI() internal pure override returns (string memory) {
return "https://boredApes.com/tokens/";
}
function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {
// the `super` keyword references the parent function of the same name
string memory uri = super.tokenURI(tokenId);
return string(abi.encodePacked(uri, ".json"));
}
}
I have a roulette smart contract, that uses another smart contract to provide it with random numbers. The issue i'm having is during compilation, i get the error:
TypeError: Type contract IRandomNumberGenerator is not implicitly convertible to expected type address.
project:/contracts/Roulette.sol:34:29:
randomNumberGenerator = IRandomNumberGenerator(randomNumberGenerator);
I'm not exactly sure where i'm going wrong, i've seen this code used in other contracts. Here is my full code, any help would be much appreciated.
// SPDX-License-Identifier: UNLICENSED"
pragma solidity ^0.8.7;
import "#openzeppelin/contracts/token/ERC20/IERC20.sol";
import "#openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "#openzeppelin/contracts/access/Ownable.sol";
import "./IRandomNumberGenerator.sol";
contract Roulette is Ownable {
using SafeERC20 for IERC20;
IERC20 public gameToken;
uint256[100] internal randomNumbers;
IRandomNumberGenerator internal randomNumberGenerator;
// ensure caller is the random number generator contract
modifier onlyRandomGenerator() {
require(msg.sender == address(randomNumberGenerator), "Only random generator");
_;
}
constructor(address tokenAddress) {
gameToken = IERC20(tokenAddress);
}
function setRandomNumberGenerator(address randomNumberGenerator) external onlyOwner {
randomNumberGenerator = IRandomNumberGenerator(randomNumberGenerator);
}
function getRandomNumber() internal onlyOwner returns (uint) {
uint result = randomNumbers[randomNumbers.length-1];
delete randomNumbers[randomNumbers.length-1];
return result;
}
function numberGenerated(uint randomNumber) external onlyRandomGenerator {
randomNumbers = expand(randomNumber);
}
// generate 100 random numbers from the random number seed
function expand(uint256 randomValue) public pure returns (uint256[] memory expandedValues) {
expandedValues = new uint256[](100);
for (uint256 i = 0; i < 100; i++) {
expandedValues[i] = uint256(keccak256(abi.encode(randomValue, i)));
}
return expandedValues;
// TODO - ensure random numbers are roulette numbers
}
}
// SPDX-License-Identifier: UNLICENSED"
pragma solidity ^0.8.7;
import "#chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "./IRoulette.sol";
contract RandomNumberGenerator is VRFConsumerBase {
address public roulette;
bytes32 internal keyHash;
uint256 internal fee;
uint256 internal randomResult;
// modifier to check if caller of owner is the admin
modifier onlyRoulette() {
require(msg.sender == roulette, "Caller to function is not the roulette contract");
_;
}
constructor(address _roulette)
VRFConsumerBase(
0xa555fC018435bef5A13C6c6870a9d4C11DEC329C, // VRF Coordinator
0x84b9B910527Ad5C03A9Ca831909E21e236EA7b06 // LINK Token
)
{
keyHash = 0xcaf3c3727e033261d383b315559476f48034c13b18f8cafed4d871abe5049186;
fee = 0.1 * 10 ** 18;
roulette = _roulette;
}
function getRandomNumber() public onlyRoulette returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
return requestRandomness(keyHash, fee);
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
randomResult = randomness;
IRoulette(roulette).numberGenerated(randomResult);
}
}
Found out the issue was having the same name for both the parameter and the variable.
Updated the function to:
function setRandomNumberGenerator(address _randomNumberGenerator) external onlyOwner {
randomNumberGenerator = IRandomNumberGenerator(_randomNumberGenerator);
}
I'm trying to get estimated eth needed to perform a swap on ropsten.
interface IUniswap {
function WETH() external pure returns (address);
function getAmountsOut(
uint amountIn,
address[] calldata path)
external
view
returns (uint[] memory amounts);
}
contract UniswapController {
address internal constant UNISWAP_ROUTER_ADDRESS = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
IUniswap public uniswapRouter;
address private UNISWAP_DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
constructor() public {
uniswapRouter = IUniswap(UNISWAP_ROUTER_ADDRESS);
}
function getEstimatedETHforToken(uint daiAmount) public view returns (uint[] memory) {
return uniswapRouter.getAmountsOut(daiAmount, getPathForETHtoDAI());
}
function getWETH() public view returns(address) {
return uniswapRouter.WETH();
}
function getPathForETHtoDAI() public view returns (address[] memory) {
address[] memory path = new address[](2);
path[0] = uniswapRouter.WETH();
path[1] = UNISWAP_DAI_ADDRESS;
return path;
}
}
When I run getEstimatedETHforToken(amount) on remix ide, I get the error:
execution reverted: UniswapV2Library: INSUFFICIENT_LIQUIDITY
I suspect I have the wrong DAI stablecoin address, but this is the address on uniswap's site, which one should I use?
There doesn't seem to be good tokens use on testnets. Just forked the mainnet using ganache-cli and infura with this tutorial and it worked just fine.
I am trying to return a value using a function of a deployed smart contract on the blockchain.
pragma solidity 0.6.2;
contract Caller {
address cont;
function changeAdd(address _change) public {
cont = _change;
}
function caller (bytes memory test) public returns(bool, bytes memory) {
bytes memory payload = abi.encodeWithSignature("callMe(bytes)", test);
(bool success, bytes memory result)= address(cont).call(payload);
return (success, (result));
}
function viewCont() public view returns(address) {
return cont;
}
}
And the deployed test contract is this:
pragma solidity 0.6.2;
contract Store {
uint counter;
function callMe(bytes calldata test) external returns(bytes memory) {
counter++;
return abi.encode(test);
}
function viewCounter () public view returns(uint256) {
return(counter);
}
function clearCounter() public {
counter = 0 ;
}
}
In this example, I am deploying contract "Store" on the blockchain where it is assigned a random address, which can be pointed at via the Caller.changeAdd function in order to use Caller.caller function. Thus, I am trying to send data in the form of bytes to the Store contract, which is supposed to send back the same data to the Caller contract. I am trying to isolate -only- the data that is originally sent, so I can use it to test interaction between smart contracts on the blockchain. I tried in the beginning to send an integer, but I couldn't find a way to do it. So I used bytes and it worked, but still the data I receive isn't the same that I send in the first place(e.g. I send 0x0 and I receive a big bytes number, which isn't the same as 0x0).
I could appreciate any help on how to receive and handle data between two different, unlinked smart contracts, thank you in advance.
Do you try to use abi.decode function of Solidity.
In the below example, contract B calls setName of contract A, then decodes the result by using abi.decode function.
contract A {
string public name;
constructor(string memory tokenName) public {
name = tokenName;
}
function setName(string memory newName) public returns ( string memory){
name = newName;
return newName;
}
}
contract B {
event Log(string msg);
string public myName;
function call(address addr, string memory newName) public {
bytes memory payload = abi.encodeWithSignature("setName(string)", newName);
(bool success, bytes memory result)= addr.call(payload);
// Decode data
string memory name = abi.decode(result, (string));
myName = name;
emit Log(name);
}
}
I deployed two contracts, one is Callee and the other is Caller. Caller consumes functions provided by Callee. Function call directly to Callee is success, however, Caller does NOT work. Actually, I'v tried different cases from internet, none of them works. Do I miss some tricky things? Below is source code:
Callee.sol
pragma solidity ^0.4.6;
contract Callee {
uint[] public values;
function getValue(uint initial) public pure returns(uint) {
return initial + 150;
}
function storeValue(uint value) public {
values.push(value);
}
function getValues() public view returns(uint) {
return values.length;
}
}
Caller.sol
pragma solidity ^0.4.6;
contract Caller {
function someAction(address addr) public returns(uint) {
Callee c = Callee(addr);
return c.getValue(100);
}
function storeAction(address addr) public returns(uint) {
Callee c = Callee(addr);
c.storeValue(100);
return c.getValues();
}
function someUnsafeAction(address addr) public returns(bool){
return addr.call(bytes4(keccak256("storeValue(uint256)")), 100);
}
}
contract Callee {
function getValue(uint initialValue) public returns(uint);
function storeValue(uint value) public;
function getValues() public returns(uint);
}
Caller is technically working, but not doing what you're expecting.
The problem is that Caller.someAction is not marked with the pure or view modifiers, so your function call is triggering a new transaction. Transaction calls can't return values (it compiles and runs, but nothing is returned).
If you change Caller.someAction to be a pure function (and, also change Callee.getValue in the interface to be pure as well to match the contract), you will get the expected 250 returned.
pragma solidity ^0.4.6;
contract Caller {
function someAction(address addr) public pure returns(uint) {
Callee c = Callee(addr);
return c.getValue(100);
}
function storeAction(address addr) public returns(uint) {
Callee c = Callee(addr);
c.storeValue(100);
return c.getValues();
}
function someUnsafeAction(address addr) public returns(bool){
return addr.call(bytes4(keccak256("storeValue(uint256)")), 100);
}
}
contract Callee {
function getValue(uint initialValue) public pure returns(uint);
function storeValue(uint value) public;
function getValues() public returns(uint);
}
In terminal:
$ truffle migrate --reset
Compiling .\contracts\Callee.sol...
Compiling .\contracts\SimpleContract.sol...
Writing artifacts to .\build\contracts
Using network 'development'.
Running migration: 1_initial_migration.js
Replacing Migrations...
... 0x58a14c93acc733bb08e4bb56978d0bb466f8aca7659673426d989ee7e0e626f3
Migrations: 0x69ed5e4d6172639ed7d3c456ea8b2f2562c7dbcd
Saving successful migration to network...
... 0x9a3831076748cc6179ef3e4b3e466c3a4a871e196376bc22c984e91e95fdc567
Saving artifacts...
Running migration: 2_deploy_contracts.js
Replacing Caller...
... 0x7be6840c86a356decacc13967d50ef4fea30e86d30d69b19fb9998ce500c95e8
Caller: 0xb8c5e079af71813acac73bff9ca8e9e068660e86
Replacing Callee...
... 0xba7f588f9119e67968a7d6ab0110d79e1ecd3003e10cce3134018d42e966c8be
Callee: 0xd5c110c2f6566fd56749ec1a11328405f9935385
Saving successful migration to network...
... 0xc1526876e365189be1529a0943042e3a25e395a5cc19930ad907a694165104f1
Saving artifacts...
$ truffle console
truffle(development)> var caller = Caller.at('0xb8c5e079af71813acac73bff9ca8e9e068660e86');
undefined
truffle(development)> caller.someAction('0xd5c110c2f6566fd56749ec1a11328405f9935385');
{ [String: '250'] s: 1, e: 2, c: [ 250 ] }