Contract.aepps.com; Error:Network Error

This post was flagged by the community and is temporarily hidden.

1 Like

Can you provide your Sophia code here so we can help you?

1 Like
contract BudgetCheck =
  record budget_allocation = {
    description:string,
    from:string,
    to:string,
     amount:int,
    _type:string,
    address:address,
    timestamp:string
    }
  record budget_spending = {
      reason:string,
      amount:int,
      description:string,
      _type: string,
      address:address,
      parentId:int,
      parentType:string,
      timestamp: string
    }   
  record state ={
    budget_allocations:map(int, budget_allocation),
    budget_spendings:map(int, budget_spending),
    totalbudget_allocations : int,
    totalbudget_spendings : int
    
    }
  function init()={
   budget_allocations = {},
   budget_spendings = {},
   totalbudget_allocations = 0,
   totalbudget_spendings = 0
   }
  
  public stateful function addBudget_allocation(description':string,from':string,to':string, _type':string, timestamp:string) =
    let budget_allocation = {
      description = description',
      from = from',
      to = to',
      _type = _type',
      amount =Call.value,
      address =Call.caller,
      timestamp = timestamp
      }
    let index = getTotalBudget_allocations() + 1
    put (state { budget_allocations [index] = budget_allocation, totalbudget_allocations = index})

  public stateful function addBudget_spending(reason':string, description':string, parentId':int, parentType':string, _type':string, timestamp':string) =
    let budget_spending = {
      reason = reason',
      description = description',
      parentId = parentId',
      parentType = parentType',
      _type =parentType',
      amount = 0,
      address =Call.caller,
      timestamp = timestamp'
      }
      
    let index = getTotalBudget_spendings() + 1
    put (state {budget_spendings [index] = budget_spending, totalbudget_spendings = index})

  public function allocateFunds(senderId:int, senderType:string, recieverId:int, recieverType:string) =
    let amount' = Call.value
    if(senderType=="budget_allocation" && amount' < getBudget_allocation(senderId).amount)
      let budget_allocation = getBudget_allocation(senderId)
      let budget_spending = getBudget_spending(recieverId)
      
      Chain.spend(budget_spending.address, amount')
      
      let updatedbudget_allocation_amount = budget_allocation.amount - amount'
      let updatedbudget_spending_amount = budget_spending.amount + amount'
      let updatedbudget_allocation = state.budget_allocations{ [senderId].amount = updatedbudget_allocation_amount}  
      let updatedbudget_spending = state.budget_spendings{ [recieverId].amount = updatedbudget_spending_amount}  
      
      put (state { budget_allocations = updatedbudget_allocation, budget_spendings = updatedbudget_spending})
    
    // I notice the error when I included the elif //
     
    elif(senderType=="buget_spending" && amount' < getbudget_spending(senderId).amount)
     
      let senderbudget_spending = getBudget_spending(senderId)
      let recieverbudget_spending = getBudget_spending(recieverId)
      
      Chain.spend(recieverbudget_spending.address, amount')
      
      let updatedSenderbudget_spending_amount = senderbudget_spending.amount - amount'
      let updatedRecieverbudget_spending_amount = recieverbudget_spending.amount + amount'
      let updatedSenderbudget_spending = state.budget_spendings{ [senderId].amount = updatedSenderbudget_spending_amount}  
      let updatedRecieverbudget_spending = state.budget_spendings{ [recieverId].amount = updatedRecieverbudget_spending_amount}  
      
      put (state { budget_spendings = updatedSenderbudget_spending, budget_spendings = updatedRecieverbudget_spending})
    else
      abort("Funds allocation failed")

  public function getBudget_allocation(index:int):budget_allocation =
   switch(Map.lookup(index,state.budget_allocations))
      None => abort("There is no budget allocation registered with the index")
      Some(x) => state.budget_allocations[index]
      
  public function getBudget_spending(index:int):budget_spending =
   switch(Map.lookup(index,state.budget_spendings))
      None => abort("There is no sub-budget spending registered with the index")
      Some(x) => state.budget_spendings[index]
      
  public function getTotalBudget_allocations():int = state.totalbudget_allocations
  public function getTotalBudget_spendings():int = state.totalbudget_spendings
1 Like

On a first look you are trying to update the same state record field at once here in the elif statement:

...
      put (state { budget_spendings = updatedSenderbudget_spending, budget_spendings = updatedRecieverbudget_spending})
...

If you update this on 2 steps first with the updatedSenderbudget_spending and after with updatedRecieverbudget_spending it will compile:

...
 let updatedSenderbudget_spending = state.budget_spendings{ [senderId].amount = updatedSenderbudget_spending_amount }  
      put (state { budget_spendings = updatedSenderbudget_spending })
 
let updatedRecieverbudget_spending = state.budget_spendings{ [recieverId].amount = updatedRecieverbudget_spending_amount }  
      put (state { budget_spendings = updatedRecieverbudget_spending })

...

Havent looked at the whole code but be sure to check it for reentrancy attacks and other security related vectors. For example here you are spending the balance first and updating the state after (this is a reentrancy possibility):

 ...
      Chain.spend(budget_spending.address, amount')
      
      let updatedbudget_allocation_amount = budget_allocation.amount - amount'
      let updatedbudget_spending_amount = budget_spending.amount + amount'
...

Spend is always done as the final step of the function execution or at least after the state update.

I’ll look over the code once again later and provide you more detailed feedback. Be sure to check out the sophia-examples repo so you get familiar with the Sophia code style and best approaches.

Cheers!

Reentrancy attacks is NOT an issue in Sophia/AEVM you are not allowed to re-enter the same contract - please don’t spread this sort of bad advice…

3 Likes

I just searched for “reentrancy attacks” and lots of things appear:

Yes, re-entrancy is in general a horrible idea so we decided to not allow that…

4 Likes