Socket contracts need to be tested with a non EVM chain to confirm that the system can be extended.
Since we are in touch with Avail team and have to add their support in near future; we want to do the mvp with them.
What does extending to non EVM chain mean?
Plugs on EVM chains should be able to connect to non EVM remotes (chainSlug+plugAddress)
Same security assumptions should apply to non EVM chain.
What does extending to non EVM chain not mean?
Porting same contracts and architecture to new chain.
It is likely that a different contract architecture makes sense for a different gas environment.
Likely change
Only the plug pointers i.e. chainSlug+plugAddress should need to be made generic (bytes)
This essentially lets the plugs define their remote counterparts while connecting.
Might need dedicated switchboards based on how verification happens.
Might need custom hasher and signature verifiers if these are not available on new chain.
hasher and signature verifiers can be upgraded to use different function based on src/dst chainSlugs.
There is a good amount of demand from developers to know the original caller on destination Plug. However I do think for alot of applications this context wont be that useful.
Given that people can already do this by adding msg.sender to the payload on the srcChain we can just attempt to create a template that devs and inherit or add quickly to their Plug that adds the msg.sender to the payload before transmitting and then also extracts the msg.sender on the destinationPlug. Somewhat like this
Under current implementation, if new attestor is added after a packet is confirmed, the packet goes back to being unconfirmed till the new attester sends their confirmation.
This needs to be avoided since a packet going from confirmed to unconfirmed state can break a lot of flows.
Solution
While attesting, mark a flag saying packet is confirmed when enough confirmations are reached.
Check this flag in allow packet.
isPacketConfirmed
### Further problem
This solution introduces another edge case.
In current outbound function, fee calculation and collection is fragmented.
Min amounts are fetched from TransmitManager, Switchboard and ExecutionManager.
Then there is a check to see if received value is enough.
After this fees are sent to 3 different places.
And these 3 places again have a min fee check.
Reasons for current flow
Having fee logic for specif components at their dedicated places makes the logic simple and modular.
Each end up having control over upgrades and collection/distribution.
Socket doesnt know how much min fees are expected at each component, and so it doenst know how much to send to them. So it needs to fetch all the fees and then distribute.
Possible improvement 1
Merge all fee logic into single component.
This removes all checks at socket level. It can simply pass all the value to fee collector.
Fee collector can check each fee individually and see if min is met.
Gas cost is reduced by a lot because only fee collector is accessed from socket and oracle is accessed only once downstream.
Makes all the fee logic coupled in single place.
Possible improvement 2
Keep 3 components, send all fees to them and have them send back remaining fees to socket.
Modular design stays.
Some gas savings but not max.
Possible improvement 3
Access oracle from socket and pass the values to all components.
The tx.gasprice can be manipulated from outside (worst case with 0 gasprice by flashbots) which affects the fees calculations in Socket.
To prevent this, we should have some external oracle giving correct values.
Switchboard defines the security settings that a plug can select.
It is the only input that needs to be taken from plugs, apart from sibling chain and address.
Switchboard should also have the fee collection and distribution logic for the defined security.
Socket is expected to call following functions on switchboard.
Function to check if packet is valid.
function allowPacket(bytes32root) externalreturns (bool) {}
Function to pay fees for verification. The fees needed for execution are included under verification for now.
The function is expected to revert if fees are not enough.
function payFees(uint256msgGasLimit) externalpayable {}
Socket DL is being build with an approach of giving integrators choice over any component/lib upgradation.
All parts need to be aligned with the ethos. Especially the ones directly in Socket contract like TransmitManager, Hasher etc.
Messages are expected to be time sensitive and sometimes fail until outside conditions are met.
Execution of failing messages needs to be discouraged.
Retry till successful execution needs to be encouraged.
Going with simple logic of no reward in fail and full fees on execution success.
Allow retries till success. (note: attack vector of executing very stale failed messages exists)
Refund
Refund of fees acts against the mechanism to establish priority market.
There can be mechanisms that involve an upper limit on priority fee but feels like unneeded complexity at base protocol.
So no refunds once fees are paid.
Send value along with message.
There can be usecases where native tokens need to be sent along with message.
This additional amount needs to be accepted on source.
The executor on destination chain can then send the required native tokens while executing and claim the collected tokens on source chain after successful execution.
There can be cases where native tokens on both chains are different and need to be converted.
For this we can reuse the oracle on source used for fee estimation.
Both original and converted amount need to be added to message metadata. (explore ways to avoid adding both)
converted amount should be checked/sent as value while making inbound call to plug.
original amount should be used for claim accounting similar to earned fees.