How can I call payable function from the A contract in B contract and send msg.value to it when invoking fund function from B contract
interface A {
receive() external payable;
}
contract B {
A a;
constructor() {
a = A("0xE9F920eE6F15739cc3b2Ac5Ea862C6eB9EEE529b");
}
function fund() public payable {
a.receive();
}
}
I get this error:
ParserError: Expected identifier but got 'receive'
--> fallback/fallback.sol:12:11:
|
12 | a.receive();
| ^^^^^^^
The receive() function is similar to the fallback function but makes it explicit that it can only receive ETH, without any implementation.
You cannot call it like that, but instead the receive() function will be called when the calldata is empty.
Change to that:
contract B {
address payable a;
constructor() {
a = payable(0xE9F920eE6F15739cc3b2Ac5Ea862C6eB9EEE529b);
}
function fund() public payable {
a.call{value: msg.value}("");
}
}
Related
I am trying the below code, elementary reentrancy example.
The current code works but transfer or send doesn't work. It reverts. What are the reasons?
Note: I chose setCaller to reenter to test the fact that updating the dirty state variable (already modified var in the same tx) takes less gas.
// SPDX-License-Identifier: Unlicensed
pragma solidity 0.8.7;
contract TestFund {
// success, if caller is itself.
address public caller;
constructor() payable {}
function getBalance() public view returns (uint) {
return address(this).balance;
}
function emptyFn(address dummy) public {}
function setCaller(address _caller) public {
caller = _caller;
}
function withdraw() external {
caller = msg.sender;
// require(payable(msg.sender).send(1 wei));
// payable(msg.sender).transfer(1 wei);
(bool success, bytes memory data) = payable(msg.sender).call{gas: 2300, value:1 wei}("");
require(success);
}
}
contract Attack {
function getBalance() public view returns (uint) {
return address(this).balance;
}
function attack(address target) external {
TestFund(target).withdraw();
}
receive() external payable {
if (getBalance() == 1 wei) {
TestFund(msg.sender).setCaller(msg.sender);
}
}
}
The following contract calls another contract using an interface method (code to change):
pragma solidity 0.8.7;
interface MyStorage {
function setStorageValue(uint256) external;
}
contract StorageFactory {
uint256 storageValue;
constructor(uint256 _storageValue) {
storage = _storageValue;
}
function initStorage(MyStorage store) public payable {
store.setStorageValue(storageValue);
address payable storeAddress = payable(address(store));
storeAddress.call{value: msg.value}("");
}
}
Following is the StorageContract (code cannot be changed):
pragma solidity 0.8.7;
contract Storage {
int _storageValue;
function setStorageValue(int storageValue) public {
_storageValue = storageValue;
}
receive() external payable {
require(_storageValue == -1 || address(this).balance <= uint(_storageValue), "Invalid storage value");
}
fallback() external {
_storageValue = -1;
}
}
I use a test to call initStorage of the first contract by passing a Storage object, where the test is meant to fail because the value is set to a large amount. But somehow, the fallback() function seems to get called, setting the value to -1. I can't figure out why. Any help is appreciated.
Due to the solidity doc:
The fallback function is executed on a call to the contract if none of the other functions match the given function signature, or if no data was supplied at all and there is no receive Ether function. The fallback function always receives data, but in order to also receive Ether it must be marked payable.
Your function getting called because there's no overloading for the function
function setStorageValue(uint256 storageValue) public
So change the storageValue from int to uint256 will help.
want to transfer funds from one contract to another
//SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.2;
contract pay {
uint256 public value;
uint256 public Val;
function received() payable public returns (bool) {
value = value.Add(msg.value).mul(95).div(100);
Val = val.add(msg.value).mul(5).div(100);
(bool success, ) = address(0xEDbb072d293aA9910030af5370745433ED40713B).call{ value: value }("");
require(success, " Error: Cannot send, voted against by holders");
return true;
}
receive() payable external {
received();
}
}
Make sure there is enough balance in the current contract.(contract pay)
check contract balanceļ¼
function getBalance() public view returns(uint){
return address(this).balance;
}
I have this error "TypeError: Return argument type address is not implicitly convertible to expected type (type of first return variable) address payable. --> Driven.sol:233:16: | 233 | return msg.sender; | ^^^^^^^^^^"
for the following function
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
Please help!
Since Solidity 0.8, msg.sender is not payable anymore. You need to cast it to payable first.
function _msgSender() internal view virtual returns (address payable) {
return payable(msg.sender); // added payable
}
Or you can return just address (not payable):
function _msgSender() internal view virtual returns (address) { // removed payable
return msg.sender;
}
I found such way, when one general interface with structure is created and then contract A and B inherit the interface with structure.
But I'm wondering if there are other ways?
And could there be a case where a contract with a structure can be updated?
pragma experimental ABIEncoderV2;
pragma solidity ^0.6.0;
interface params {
struct structTest {
uint256 data;
}
}
contract contractA is params{
function testCall(structTest calldata _structParams) public pure returns (uint256){
return _structParams.data;
}
}
contract contractB is params{
contractA aContractInstance;
constructor (address _a) public {
aContractInstance = contractA(_a);
}
function test(structTest calldata _structParams) public view returns(uint256){
// call contract A from B and pass structure
return aContractInstance.testCall(_structParams);
}
}
interface IContractA {
struct User {
address addr;
}
function getUser(aaddress addr) external view returns (User memory user);
}
contract contractB{
function getUserFromContractA(address addr) public view
returns (IContractA.User memory user)
{
ContractA = IContractA(addrContractA);
user = ContractA.getUser(addr);
}
}