Multiple indexed event fields are not supported by web3j? - events

I'm having Ethereum smart contract with function:
event onPledged(uint indexed featureKey, uint date, address backer, uint256 amount);
...
function pledge(uint featureKey) public
payable
withState(featureKey, State.Funding)
{
...
// event
onPledged(featureKey, now, backer, pledgeAmount);
...
}
I'm having java test (using web3j and web3j-maven-plugin to generate smart contract java wrapper) to call pledge() that checks events:
// pledge
logger.info("Pledging by backer ...");
TransactionReceipt pledgeReceipt = pledgerContract.pledge(featureKey, fixedPledgeAmount).send();
List<AppetissimoContract.OnPledgedEventResponse> pledgedEvents = minerContract.getOnPledgedEvents(pledgeReceipt);
assertEquals(1, pledgedEvents.size()); // true
If i change backer event field to be indexed the test starts to fail:
event onPledged(uint indexed featureKey, uint date, address indexed backer, uint256 amount);
Now it's fails as there were no events (0):
assertEquals(1, pledgedEvents.size()); // false, size() is 0
In solidity docs it's written that up to 3 fields can be indexed:
> Up to three parameters can receive the attribute indexed which will cause the respective arguments to be searched for: It is possible to filter for specific values of indexed arguments in the user interface.
Is it web3j issue? Does using of indexed attribute require more gas (so reaching gas limit can be the reson)?

this is an outstanding bug with web3j. Right now you have to order all of the indexed parameters before the non-indexed parameters to work around this.

Related

Chainlink Keeper not performing upkeep

I have a contract that is using Chainlink keepers for upkeep but the checkUpKeep/performUpkeep is not running. I have sufficiently funded the upkeep to ensure it has a high balance. The code from the contract was previously deployed, but now contains a minor change (outside the Chainlink functions), and the previous contract is receiving upkeeps. My code for checkUpKeep and performUpKeep are below:
function **checkUpkeep**(bytes calldata /* checkData */) external view override returns (bool upkeepNeeded, bytes memory /* performData */) {
if(lottery_state == LOTTERY_STATE.OPEN){
upkeepNeeded = (block.timestamp - lastTimeStamp) >= duration;
}
else{
upkeepNeeded = false;
}
}
function **performUpkeep**(bytes calldata /* performData */) external override {
require(msg.sender == 0x4Cb093f226983713164A62138C3F718A5b595F73);
lottery_state = LOTTERY_STATE.DRAWING;
Random(random).getRandomNumber();
}
As I mentioned earlier, this code is being used in another contract which is currently receiving upkeep so I am puzzled as to why it is not working in the new contract.
If your upkeeps are not being performed make sure to double-check the next items:
Are Chainlink Keepers currently available on the network you are deploying to?
Is your smart contract KeeperCompatible?
Call checkUpkeep. Did it return true or false?
Can you performUpkeep?
Did you register your contract for upkeeps?
Did you fund it?

What is balanceRecived in solidity? what it will be strore?

i am begginer can any one explain me what is balanceRecived in solidity? what it will be strore?
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.1;
contract SendMoneyExample {
uint public balanceReceived;
function receiveMoney() public payable {
balanceReceived += msg.value;
}
function getBalance() public view returns(uint) {
return address(this).balance;
}
function withdrawMoney() public {
address payable to = payable(msg.sender);
to.transfer(getBalance());
}
}
Each time when someone executes the receiveMoney() function, it happens as a result of a transaction.
A transaction can hold value in the form of the network native currency. Your question is tagged Ethereum, and the native currency for the Ethereum network is ETH. (If the contract was on the Binance Smart Chain network, the native currency would be BNB, the Tron network has TRX, and so on...)
So each time the receiveMoney() function is executed, in adds the current transaction value to the total number hold in balanceReceived.
Example:
First transaction executing receiveMoney(), sending along 1 wei (the smallest unit of ETH). The value of balanceReceived becomes 1.
Second transaction executing receiveMoney(), sending along 5 wei. The value of balanceReceived becomes 6.

How to call different contract from its address?

In solidity (ethereum) one needs the contract address to call that contract.
contract KittyInterface {
function getKitty(uint256 _id) external view returns (
bool isGestating,
bool isReady,
uint256 cooldownIndex,
uint256 nextActionAt,
uint256 siringWithId,
uint256 birthTime,
uint256 matronId,
uint256 sireId,
uint256 generation,
uint256 genes
);
}
contract ZombieFeeding is ZombieFactory {
address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
KittyInterface kittyContract = KittyInterface(ckAddress);
Can I do that in near protocol?
The examples in near are something different which requires supplying the wasm file.
https://github.com/near-examples/rust-high-level-cross-contract
pub fn deploy_status_message(&self, account_id: String, amount: u64) {
Promise::new(account_id)
.create_account()
.transfer(amount as u128)
.add_full_access_key(env::signer_account_pk())
.deploy_contract(
include_bytes!("../status-message-contract/status_message.wasm").to_vec(),
);
}
Also, I am getting errors while using the high level cross contract code. https://gateway.ipfs.io/ipfs/QmPvcjeEE5PJvaJNN2axgKVWGbWVEQCe9q4e95t9NCeGFt/
Take a look at the lockup contract example instead. It uses the following:
ext_whitelist::is_whitelisted(
staking_pool_account_id.clone(),
&self.staking_pool_whitelist_account_id,
NO_DEPOSIT,
gas::whitelist::IS_WHITELISTED,
)
.then(ext_self_owner::on_whitelist_is_whitelisted(
staking_pool_account_id,
&env::current_account_id(),
NO_DEPOSIT,
gas::owner_callbacks::ON_WHITELIST_IS_WHITELISTED,
))
from https://github.com/near/core-contracts/blob/cd221798a77d646d5f1200910d45326d11951732/lockup/src/owner.rs#L29-L40
The first call interface is (<arg_0>, <arg_1>, ..., <arg_n>, <ACCOUNT_ID>, <ATTACHED_DEPOSIT>, <ATTACHED_GAS>)
<arg_0>, <arg_1>, ..., <arg_n> - arguments from the interface defined below
<ACCOUNT_ID> - the account where the contract to call is deployed
<ATTACHED_DEPOSIT> - the amount in yocto-NEAR to attach to the call
<ATTACHED_GAS> - the amount of Gas to pass to the call
It later attached a callback to the first promise using .then. The callback is just another async function call.
The high-level interface ext_whitelist is defined like this:
#[ext_contract(ext_whitelist)]
pub trait ExtStakingPoolWhitelist {
fn is_whitelisted(&self, staking_pool_account_id: AccountId) -> bool;
}
from https://github.com/near/core-contracts/blob/cd221798a77d646d5f1200910d45326d11951732/lockup/src/lib.rs#L64-L67

How to create a CRUD with gRPC service without much repetition?

I'm trying to use gRPC to build a simple CRUD service, but I keep finding myself creating messages with big overlaps.
This is best described by an example:
message Todo {
// id is only available for a persisted entity in database.
string id = 1;
string content = 2;
// this is only available for users with admin role.
string secret_content = 3;
}
service Todos {
rpc CreateTodo(CreateRequest) returns (CreateResponse) {}
rpc ReadTodo(ReadRequest) returns (ReadResponse) {}
}
message CreateRequest {
// this todo is not supposed to have id,
// should I create another version of Todo without an id field?
Todo todo
}
message CreateResponse {
// this todo will always have an id.
Todo todo = 1;
}
message ReadRequest {
string id = 1;
}
message ReadResponse {
// this todo should only have the secret_content field if the
// user is authenticated as an admin, if not, the field should not
// fallback to the zero value, the whole field must be missing.
Todo todo = 1;
}
Is this a good approach to build a CRUD like resource with gRPC? That is, having a single message (Todo) representing the resource, and wrapping this message in response/request types per action.
Should the Todo type message have all fields covered by all requests/responses, and not set the ones which are not in use by each?
Should the Todo type message have all fields covered by all requests/responses, and not set the ones which are not in use by each?
Yes, this seems like a reasonable design. In protobuf v2, you would have marked such fields optional to make it easier to understand. But in v3, all fields are optional by default anyway.

Domain Driven Design - complex validation of commands across different aggregates

I've only began with DDD and currently trying to grasp the ways to do different things with it. I'm trying to design it using asynchronous events (no event-sourcing yet) with CQRS. Currently I'm stuck with validation of commands. I've read this question: Validation in a Domain Driven Design , however, none of the answers seem to cover complex validation across different aggregate roots.
Let's say I have these aggregate roots:
Client - contains list of enabled services, each service can have a value-object list of discounts and their validity.
DiscountOrder - an order to enable more discounts on some of the services of given client, contains order items with discount configuration.
BillCycle - each period when bills are generated is described by own billcycle.
Here's the usecase:
Discount order can be submitted. Each new discount period in discount order should not overlap with any of BillCycles. No two discounts of same type can be active at the same time on one service.
Basically, using Hibernate in CRUD style, this would look something similar to (java code, but question is language-agnostic):
public class DiscountProcessor {
...
#Transactional
public void processOrder(long orderId) {
DiscOrder order = orderDao.get(orderId);
BillCycle[] cycles = billCycleDao.getAll();
for (OrderItem item : order.getItems()) {
//Validate billcycle overlapping
for (BillCycle cycle : cycles) {
if (periodsOverlap(cycle.getPeriod(), item.getPeriod())) {
throw new PeriodsOverlapWithBillCycle(...);
}
}
//Validate discount overlapping
for (Discount d : item.getForService().getDiscounts()) {
if (d.getType() == item.getType() && periodsOverlap(d.getPeriod(), item.getPeriod())) {
throw new PeriodsOverlapWithOtherItems(...);
}
}
//Maybe some other validations in future or stuff
...
}
createDiscountsForOrder(order);
}
}
Now here are my thoughts on implementation:
Basically, the order can be in three states: "DRAFT", "VALIDATED" and "INVALID". "DRAFT" state can contain any kind of invalid data, "VALIDATED" state should only contain valid data, "INVALID" should contain invalid data.
Therefore, there should be a method which tries to switch the state of the order, let's call it order.validate(...). The method will perform validations required for shift of state (DRAFT -> VALIDATED or DRAFT -> INVALID) and if successful - change the state and transmit a OrderValidated or OrderInvalidated events.
Now, what I'm struggling with, is the signature of said order.validate(...) method. To validate the order, it requires several other aggregates, namely BillCycle and Client. I can see these solutions:
Put those aggregates directly into the validate method, like
order.validateWith(client, cycles) or order.validate(new
OrderValidationData(client, cycles)). However, this seems a bit
hackish.
Extract the required information from client and cycle
into some kind of intermediate validation data object. Something like
order.validate(new OrderValidationData(client.getDiscountInfos(),
getListOfPeriods(cycles)).
Do validation in a separate service
method which can do whatever it wants with whatever aggregates it
wants (basically similar to CRUD example above). However, this seems
far from DDD, as method order.validate() will become a dummy state
setter, and calling this method will make it possible to bring an
order unintuitively into an corrupted state (status = "valid" but
contains invalid data because nobody bothered to call validation
service).
What is the proper way to do it, and could it be that my whole thought process is wrong?
Thanks in advance.
What about introducing a delegate object to manipulate Order, Client, BillCycle?
class OrderingService {
#Injected private ClientRepository clientRepository;
#Injected private BillingRepository billRepository;
Specification<Order> validSpec() {
return new ValidOrderSpec(clientRepository, billRepository);
}
}
class ValidOrderSpec implements Specification<Order> {
#Override public boolean isSatisfied(Order order) {
Client client = clientRepository.findBy(order.getClientId());
BillCycle[] billCycles = billRepository.findAll();
// validate here
}
}
class Order {
void validate(ValidOrderSpecification<Order> spec) {
if (spec.isSatisfiedBy(this) {
validated();
} else {
invalidated();
}
}
}
The pros and cons of your three solutions, from my perspective:
order.validateWith(client, cycles)
It is easy to test the validation with order.
#file: OrderUnitTest
#Test public void should_change_to_valid_when_xxxx() {
Client client = new ClientFixture()...build()
BillCycle[] cycles = new BillCycleFixture()...build()
Order order = new OrderFixture()...build();
subject.validateWith(client, cycles);
assertThat(order.getStatus(), is(VALID));
}
so far so good, but there seems to be some duplicate test code for DiscountOrderProcess.
#file: DiscountProcessor
#Test public void should_change_to_valid_when_xxxx() {
Client client = new ClientFixture()...build()
BillCycle[] cycles = new BillCycleFixture()...build()
Order order = new OrderFixture()...build()
DiscountProcessor subject = ...
given(clientRepository).findBy(client.getId()).thenReturn(client);
given(cycleRepository).findAll().thenReturn(cycles);
given(orderRepository).findBy(order.getId()).thenReturn(order);
subject.processOrder(order.getId());
assertThat(order.getStatus(), is(VALID));
}
#or in mock style
#Test public void should_change_to_valid_when_xxxx() {
Client client = mock(Client.class)
BillCycle[] cycles = array(mock(BillCycle.class))
Order order = mock(Order.class)
DiscountProcessor subject = ...
given(clientRepository).findBy(client.getId()).thenReturn(client);
given(cycleRepository).findAll().thenReturn(cycles);
given(orderRepository).findBy(order.getId()).thenReturn(order);
given(client).....
given(cycle1)....
subject.processOrder(order.getId());
verify(order).validated();
}
order.validate(new OrderValidationData(client.getDiscountInfos(),
getListOfPeriods(cycles))
Same as the above one, you still need to prepare data for both OrderUnitTest and discountOrderProcessUnitTest. But I think this one is better as order is not tightly coupled with Client and BillCycle.
order.validate()
Similar to my idea if you keep validation in the domain layer. Sometimes it is just not any entity's responsibility, consider domain service or specification object.
#file: OrderUnitTest
#Test public void should_change_to_valid_when_xxxx() {
Client client = new ClientFixture()...build()
BillCycle[] cycles = new BillCycleFixture()...build()
Order order = new OrderFixture()...build();
Specification<Order> spec = new ValidOrderSpec(clientRepository, cycleRepository);
given(clientRepository).findBy(client.getId()).thenReturn(client);
given(cycleRepository).findAll().thenReturn(cycles);
subject.validate(spec);
assertThat(order.getStatus(), is(VALID));
}
#file: DiscountProcessor
#Test public void should_change_to_valid_when_xxxx() {
Order order = new OrderFixture()...build()
Specification<Order> spec = mock(ValidOrderSpec.class);
DiscountProcessor subject = ...
given(orderingService).validSpec().thenReturn(spec);
given(spec).isSatisfiedBy(order).thenReturn(true);
given(orderRepository).findBy(order.getId()).thenReturn(order);
subject.processOrder(order.getId());
assertThat(order.getStatus(), is(VALID));
}
Do the 3 possible states reflect your domain or is that just extrapolation ? I'm asking because your sample code doesn't seem to change Order state but throw an exception when it's invalid.
If it's acceptable for the order to stay DRAFT for a short period of time after being submitted, you could have DiscountOrder emit a DiscountOrderSubmitted domain event. A handler catches the event and (delegates to a Domain service that) examines if the submit is legit or not. It would then issue a ChangeOrderState command to make the order either VALIDATED or INVALID.
You could even suppose that the change is legit by default and have processOrder() directly take it to VALIDATED, until proven otherwise by a subsequent INVALID counter-order given by the validation service.
This is not much different from your third solution or Hippoom's one though, except every step of the process is made explicit with its own domain event. I guess that with your current aggregate design you're doomed to have a third party orchestrator (as un-DDD and transaction script-esque as it may sound) that controls the process, since the DiscountOrder aggregate doesn't have native access to all information to tell if a given transformation is valid or not.

Resources