4

I'm trying calculate tax on arbitrary items/values. To do this I have a single contract is used as an 'Oracle' to get the tax from an external system. This contract defines functions to be called from other contracts and will emit an event that is captured by the external code. This will then perform the calculations and send the data back to the contract. The code is

pragma solidity ^0.4.21;

contract TaxContract {
    address public owner;
    event TaxRequest(int price);

    constructor() public {
       owner = msg.sender;
    }

    function calculateTax(int price) public {
       emit TaxRequest(price);
    }
}

The calling contract is passed the address of the TaxContract in it's constructor.

pragma solidity ^0.4.21;

import "./TaxContract.sol";

// Asset Test Contract
contract AssetContract {
    address public owner;
    address contractAddress;

    // Constructor
    constructor(address taxContractAddress) public {
        owner = msg.sender;
        contractAddress = taxContractAddress;
    }

    // Public functions
    function sellAsset(int price) public {
        TaxContract(contractAddress).calculateTax(price);
    }
}

I'm using Nethereum to both deploy the contracts and listen for events i.e

var sellFunction = contract.GetFunction("sellAsset");
var gasLimit = await sellFunction.EstimateGasAsync().ConfigureAwait(false);
await sellFunction.SendTransactionAndWaitForReceiptAsync(senderAddress, gasLimit, null, null, 563278);

and

var taxRequestEvent = contract.GetEvent("TaxRequest");
var taxFilter = await taxRequestEvent.CreateFilterAsync();

while (true)
{
var taxEvent = await taxRequestEvent.GetFilterChanges<SalesTaxRequestEvent>(taxFilter);
....

When I had all of the functionality in one contract i.e the sellAsset method emitted the event that the external code was listening for and called the sellAsset function it all worked. But now that I have split it into two separate contracts, no event seems to be fired. Any ideas as to why this is not working?

0

Setting aside some experimental work that uses assembler to explore event logs, you can't read event logs from a contract. Contracts that send internal transactions (a.k.a. messages) can read return values. So, consider changing the calculateTax() function so it can "send the data back to the contract".

function calculateTax(int price) public returns(int) {
   emit TaxRequest(price);
   return price;
}

Then in AssetContract

// Public functions
function sellAsset(int price) public {
    int tax = TaxContract(contractAddress).calculateTax(price);
}

As an aside, I think uint would work unless you anticipate negative tax rates.

Hope it helps.

  • I probably did not explain this correctly. I'm trying to capture the event in an external application which will perform the calculation and place the data back onto the chain. So this code does not help. – ColinB Jul 31 '18 at 13:53
0

I had a similar situation as yours, where I needed to capture events generated by a contract called from my caller contact.

I solved it by using GetAllChanges something like this:

var receipt = await sellFunction.SendTransactionAndWaitForReceiptAsync(senderAddress, gasLimit, null, null, 563278);
var taxRequestEvent = contract.GetEvent("TaxRequest");
var taxFilter = await taxRequestEvent.CreateFilterAsync( new BlockParameter(receipt.BlockNumber), new BlockParameter(receipt.BlockNumber));
var taxEvents = await taxRequestEvent.GetAllChanges<SalesTaxRequestEvent>(taxFilter);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.