Unlocking capital efficiency and interchain functionality

CALC-DCA v1.1.3 & v1.2.3

Calculated Finance (CALC) 🧮
3 min readDec 9, 2022

Overview

With the successful release of CALC’s MVP DCA vaults, there has been lots of great community feedback and discussion which will help shape the future of CALC. The team have been working hard and are excited to announce the first of many new releases to come — as we work towards building out some of the best-in-class mid-to-long term investment tools.

This release will come in two parts (v1.1.3 & v1.2.3) with the migration of data taking place between each release. This new functionality will pave the way for an integration with Kujira’s Bow protocol and IBC staking.

NOTE: These changes will NOT impact existing DCA strategies — users are NOT required to do anything.

Motivation

The main motivation behind v1.1.3 and v1.2.3 is to reduce the complexity of future integrations (Bow & IBC) by making some of our data structures more flexible. By refactoring two key data structures within the codebase (Destinations & Events), we will be able to introduce new smart contract logic without having to continually make complicated data migrations. This means that integrating with new DeFi protocols becomes much simpler.

Release plan

In order to get to the place where the codebase has greater flexibility we need to migrate away from two existing data structures which will need to take place over two contract upgrades. The first migration will start saving data to both existing and new indexes, and the second migration will remove the deprecated index. These changes will occur over 96 hours (two governance proposals) and will have no impact on users currently using CALC.

v1.1.3

  • Introduce a new index to start storing events as Binary in addition to storing them in their deserialised form Event
pub struct EventIndexes<'a> {
pub resource_id: UniqueIndex<'a, (u128, u64), Event, u64>,
}

pub struct SerialisedEventIndexes<'a> {
pub resource_id: UniqueIndex<'a, (u128, u64), Binary, u64>,
}
  • Introduce an even migration endpoint which will save all existing events into the new event index as a Binary
pub fn migrate_previous_events(
store: &mut dyn Storage,
limit: &mut u64,
) -> Result<Response, ContractError> {
let mut event_to_migrate_id = serialised_event_store()
.range(store, None, None, cosmwasm_std::Order::Ascending)
.take(1 as usize)
.map(|result| from_binary(&result.unwrap().1).unwrap())
.collect::<Vec<Event>>()
.first()
.expect("earliest migrated event id")
.id
- 1;

while event_to_migrate_id > 0 && limit > &mut 0 {
let event_to_migrate = event_store().load(store, event_to_migrate_id)?;

serialised_event_store().save(
store,
event_to_migrate.id,
&to_binary(&event_to_migrate).expect("serialised event"),
)?;

event_to_migrate_id -= 1;
*limit -= 1;
}

if event_to_migrate_id == 0 {
return Err(ContractError::CustomError {
val: "All events have been migrated".to_string(),
});
}

return Ok(
Response::new().add_attribute("last_event_migrated_id", event_to_migrate_id.to_string())
);
}
  • Deprecating the destinationsfield on vaults in favour of storing destinations at a seperate index as a Binary
const DESTINATIONS: Map<u128, Binary> = Map::new("destinations_v20");
  • Update vault building logic to read from new destinations index
fn vault_from(
data: &VaultDTO,
pair: Pair,
trigger: Option<TriggerConfiguration>,
destinations: &mut Vec<Destination>,
) -> Vault {
destinations.append(
&mut data
.destinations
.clone()
.into_iter()
.map(|destination| Destination {
address: destination.address,
allocation: destination.allocation,
action: match destination.action {
PostExecutionActionDeprecated::Send => PostExecutionAction::Send,
PostExecutionActionDeprecated::ZDelegate => PostExecutionAction::ZDelegate,
},
})
.collect(),
);

v1.2.3

  • Remove the old event index
  • Remove the event migration endpoint
  • Update read endpoints to use new event index
pub fn event_store<'a>() -> IndexedMap<'a, u64, Binary, EventIndexes<'a>> {
let indexes = EventIndexes {
resource_id: UniqueIndex::new(
|event| {
from_binary(&event)
.map(|event: Event| (event.resource_id.into(), event.id))
.expect("deserialised event")
},
"serialised_events_v20__resource_id",
),
};
IndexedMap::new("serialised_events_v20", indexes)
}

Conclusion

The team looks forward to the continued community involvement and support for building out the future of CALC Finance.

--

--

Calculated Finance (CALC) 🧮

CALC is transforming the average retail investor into a calculated & educated, long-term investor.