I have a question about the RSK integration (specifically about how callback addresses are used)
https://github.com/smartcontractkit/chainlink-RSK/blob/master/test-runner/src/contracts/Consumer.sol
function requestRIFPriceByCallback(uint256 _payment, address _callback) public {
Chainlink.Request memory req = buildChainlinkRequest(specId, _callback, this.fulfill.selector);
req.add("get", "https://api.liquid.com/products/580");
req.add("path", "last_traded_price");
req.addInt("times", 100000000);
sendChainlinkRequest(req, _payment);
}
https://github.com/smartcontractkit/chainlink/blob/develop/evm-contracts/src/v0.4/tests/Consumer.sol
function requestEthereumPrice(string _currency) public {
Chainlink.Request memory req = buildChainlinkRequest(specId, this, this.fulfill.selector);
req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY");
string[] memory path = new string[](1);
path[0] = _currency;
req.addStringArray("path", path);
sendChainlinkRequest(req, ORACLE_PAYMENT);
}
These are from Consumer.sol (above from RSK and below from original)
Why does the RSK consumer require a callback address and what does that do/how does it work?
Both of these functions have callback addresses. You’ll see in the second method they just use ‘this’. The callback address is a parameter in the ‘buildChainlinkRequest’ function. It specifies which contract to return the data to. That combined with the function selector lets you pick which contract and function you want to return your data to.
The 2nd method doesn’t have a callback address because it’s set to ‘this’. The first function lets you pick.
Related
In the Remix, getICOMembers function works appropriately and returns all members of a specific ICO type after they are added to the icoMembers mapping.
mapping(uint256 => address[]) private icoMembers;
function getICOMembers(uint256 _icoType) external view onlyOwner returns (address[] memory)
{
return icoMembers[_icoType];
}
0 1
But Etherscan gives this error even if I connected by owner address.
deployer address owner address etherscan error
Also, this function has onlyOwner modifier too but it works.
ICOdata[] private ICOdatas;
function getICODatas() external view onlyOwner returns (ICOdata[] memory)
{
return ICOdatas;
}
getICODatas function output
I tried to add members by hardcoding instead of joining the token sale function, changing external to public but it still gives the same error.
Also, this is the constructor.
constructor(
address _token,
address payable _usdtWallet,
address _vestingContract
) {
require(
address(_token) != address(0),
"ERROR at Crowdsale constructor: Token contract address shouldn't be zero address."
);
require(
_usdtWallet != address(0),
"ERROR at Crowdsale constructor: USDT wallet address shouldn't be zero address."
);
require(
_vestingContract != address(0),
"ERROR at Crowdsale constructor: Vesting contract address shouldn't be zero address."
);
token = ERC20(_token);
usdtWallet = _usdtWallet;
totalAllocation = 0;
vestingContract = IVesting(_vestingContract);
transferOwnership(msg.sender);
}
A view function is usually invoked using a read-only call - not using a transaction.
Unlike transaction, a call is not signed by any private key. So you can specify any from address that is reflected as the value of msg.sender.
Then it depends on the specific implementation of the UI and of the node that processes the call. My guess is that Remix IDE uses the currently selected address from the accounts list as msg.sender (which passes the onlyOwner validation), while Etherscan uses the zero address (which fails the validation).
I have a contract function like the following
function updateDeps(uint16 parent, uint16[] calldata deps) public
And I am trying to create unit tests in remix with the following
contract TestContract is MyContract {
uint16[] deps;
function testUpdateDeps() {
deps.push(uint16(2));
deps.push(uint16(3));
deps.push(uint16(4));
(bool success, bytes memory result) = address(this).delegatecall(abi.encodeWithSignature("updateDeps(uint16, uint16[])", 1, deps));
Assert.ok(success, "should succeed");
}
}
I wrote the test like this because of the difference between fixed size array and dynamic array and that calldata cannot be a contract variable and can only be created in function call, thus the delegatecall. However, the transaction failed.
How should I test function that takes a calldata dynamic array as param?
It is with the abi encoding string, there cannot be space between the params in the string, i.e. updateDeps(uint16,uint16[]) works but not updateDeps(uint16, uint16[])
P.S. an additional fyi, if you are using uint in your code, which is alias for uint256, in the abi signature string you have to specify uint256 but not uint.
function sendGift(uint256 _mintAmount,address recipient) public payable {
uint256 supply = totalSupply();
require(!paused);
require(_mintAmount > 0);
require(_mintAmount <= maxMintAmount);
require(supply + _mintAmount<= availableSupplyForSale);
//require(_amount >= cost * _mintAmount);
require(coinToken.allowance(msg.sender,address(this))>=cost * _mintAmount);
coinToken.transferFrom(msg.sender, address(this),cost * _mintAmount);
if(supply<currentSupply){
for (uint256 i = 1; i <= _mintAmount; i++) {
_safeMint(recipient, supply + i);
}
}
else{
uint256[] memory tokenIds = walletOfOwner(address(this));
for(uint256 i=1;i<=_mintAmount;i++)
transferFrom(address(this),recipient,tokenIds[i]);
}
}
Do I need to use payable here? Contract does not take any matic. It only takes custom token as payment .
(bool os, ) = payable(admin).call{value: address(this).balance}("");
require(os);
Also since I am not taking any matic, will this above line necessary for withdraw assets from contract as an owner? I have a sense that this above line only is useful to withdraw eth/polygon.
I am a new blockchain kid. Please help.
The payable modifier of a function is required when your function accepts native tokens (ETH, BNB, MATIC, ... depending on the network).
So in this case, you can safely remove it from the function header.
// removed `payable`
function sendGift(uint256 _mintAmount,address recipient) public {
The low-level .call() also doesn't require using payable to send native tokens.
payable(admin).call{value: address(this).balance}("");
However, if you used the high-level .transfer(), then you'd need to cast the admin variable type address to its extension type address payable using the typecasting function.
// will not work as it's type `address`
admin.transfer(address(this).balance);
// need to cast type `address` to type `address payable`
payable(admin).transfer(address(this).balance);
In order to withdraw tokens from your contract address, you need to invoke the transfer() function (defined in the ERC-20 standard) on the token contract. Do not confuse it with the native transfer() function of address payable, these are two separate things, just with the same name.
interface IERC20 {
function transfer(address, uint256) external returns (bool);
}
contract MyContract {
function withdrawToken() {
IERC20(tokenContractAddress).transfer(recipient, amount);
}
}
I made a dynamic array variable of address type, i.e.,
address payable[] public participant;
which one is the correct way to write in the following and why,
uint payable[] public participant;
or
uint[] payable public participant;
enter code here
There's address and its extension address payable, which allows you to use the native transfer() method to send ETH to this address.
Since the type is called address payable, you can make an array of this type by appending the [] expression after the type name.
There's no payable extension to uint. If your aim is to define an amount to be sent, that can be stored in a regular uint.
pragma solidity ^0.8;
contract MyContract {
address payable[] public participants;
function foo() public {
uint amount = 1; // 1 wei
for (uint i = 0; i < participants.length; i++) {
participants[i].transfer(amount);
}
}
}
I am implementing a factory pattern contract and on my constructor I want to trigger a function which deposits into the contract
--Factory--
function newChild() {
Child child = new Child(potentialPayoutAmount);
children[_childId] = address(child);
}
function getChild()view public returns (address) {
return children[_campaignId];
}
--Child Contract--
address payable public spender;
constructor(uint256 _potentialPayoutAmount) {
autoDeposit(_potentialPayoutAmount)
}
function autoDeposit(uint256 _potentialPayoutAmount) {
depositedFor[receiver] = depositedFor[receiver] + _potentialPayoutamount;
}
So my problem is that I want the spender address in the child contract to be the account that is spending the money, even though the autoDeposit function is obviously being triggered from the factory contract.
Any suggestions would help. Happy to elaborate if I was unclear.
Thanks!