Vale and GM Sign Long-Term Nickel Supply Agreement in Canada Critical to North American EV Supply Chain
Recent searches
Quick Links
•
Vale and GM Sign Long-Term Nickel Supply Agreement in Canada Critical to North American EV Supply Chain
TORONTO and DETROIT – Vale Canada Limited, a subsidiary of Vale, and General Motors Co. (NYSE: GM), announced today they have signed a term sheet for the long-term supply of battery grade nickel sulfate from Vale’s proposed plant at Bécancour, Québec, Canada. This agreement secures for GM a supply of nickel sulfate from a U.S. free-trade partner to support its fast-growing EV production needs in North America.
Under terms of the agreement, Vale will supply battery grade nickel sulfate, equivalent to 25,000 metric tons per year of contained nickel, for use in GM’s Ultium battery cathodes, which will power a broad portfolio of electric vehicles including the Chevrolet Silverado EV, Blazer EV and Equinox EV, the Cadillac LYRIQ, the GMC Sierra EV, and the GMC HUMMER EV Pickup and SUV. The amount of contained nickel is sufficient to supply approximately 350,000 EVs annually. Deliveries are targeted to commence in the second half of 2026.
This initiative highlights Vale’s uniquely strategic position to be the supplier of choice to the EV industry, leveraging its low-carbon footprint and market-leading position as North America’s largest producer of finished nickel. Nickel sulfate is the chemical compound used in the production of pre-cathode active materials for nickel-based lithium-ion batteries.
“This is a momentous agreement for Vale Base Metals that brings a key partner in GM into this first-of-its-kind facility for Canada and North America,” said Vale Executive Vice President of Base Metals, Deshnee Naidoo. “The proposed nickel sulfate project would utilize high purity, low-carbon nickel from our Canadian refineries and is a natural extension for the business, offering diversified sales and a fast entry and anchor point into the North American electric vehicle market. We look forward to continuing engagements with the governments of Canada and Quebec on this strategic critical mineral project.”
“GM’s dedicated cross-functional organization — including experts from global purchasing and supply chain, corporate development, legal, finance and treasury — is strictly focused on building a secure, sustainable, scalable and cost-competitive EV supply chain,” said Doug Parks, GM executive vice president of Global Product Development, Purchasing and Supply Chain. “Their work has already allowed GM to sign multiple binding agreements to secure the battery raw material to support 1 million units of annual EV capacity in North America in 2025. This new agreement with Vale reinforces GM’s leadership in building a secure and sustainable North America EV supply chain and will provide GM with significant supply of high-grade nickel sulfate from a low-carbon source.”
“In addition, Canada continues to play an important role in GM’s all-electric future and the material sourced from Vale will help support EV eligibility for consumer incentives under the new clean energy tax credits in the U.S.,” said Parks.
Vale and GM have also agreed to study collaborative ways to partner on advanced technology development and commercialization pathways to harvest recycled metals.
“This announcement between Vale and GM builds on Canada’s world-leading EV battery industry,” said the Honorable François-Philippe Champagne, Canada’s Minister of Innovation, Science and Industry. “It’s become even more clear that Canada can be the supplier of choice for the electric cars of the future. By leveraging Canadian critical minerals, we will see more jobs for Canadians, a growing economy and a greener and cleaner future for everyone.”
“The signing of this agreement confirms that the biggest players in the industry want to invest here and enter our supply chain. We have the resources and the expertise to produce the cleanest battery in the world, and this news will certainly contribute to that,” said Pierre Fitzgibbon, Québec's Minister of Economy, Innovation and Energy, Minister Responsible for Regional Economic Development and Minister Responsible for the Metropolis and the Montréal Region.
Vale S.A.’s base metals business is one of the world's largest producers of high-quality nickel and an important producer of copper and responsibly sourced cobalt. With headquarters in Toronto, Canada, and operations in Newfoundland & Labrador, Ontario, Manitoba, Indonesia and Brazil, the business delivers critical building blocks for a cleaner, greener future.
General Motors (NYSE:GM) is a global company focused on advancing an all-electric future that is inclusive and accessible to all. At the heart of this strategy is the Ultium battery platform, which will power everything from mass-market to high-performance vehicles. General Motors, its subsidiaries and its joint venture entities sell vehicles under the Chevrolet, Buick, GMC, Cadillac, Baojun and Wuling brands. More information on the company and its subsidiaries, including OnStar, a global leader in vehicle safety and security services, can be found at https://www.gm.com.
The following has evaluated to null or missing: ==> restClient.get("/headless-admin-taxonomy/v1.0/sites/" + groupId + "/taxonomy-vocabularies?filter=name eq 'News topics' or name eq 'Temas de notícias'&fields=id&restricFields=actions,availableLanguages&page=1&pageSize=1").items [in template "44549#44620#460359" at line 4, column 29] ---- Tip: It's the step after the last dot that caused this error, not those before it. ---- Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)?? ---- ---- FTL stack trace ("~" means nesting-related): - Failed at: newsTopicVocabularyId = restClient.ge... [in template "44549#44620#460359" at line 4, column 5] ----
1<#assign
2 images_path = "/documents/d/guest/"
3 namespace = "com_liferay_asset_publisher_web_portlet_AssetPublisherPortlet_" + stringUtil.randomId()
4 newsTopicVocabularyId = restClient.get("/headless-admin-taxonomy/v1.0/sites/" + groupId + "/taxonomy-vocabularies?filter=name eq 'News topics' or name eq 'Temas de notícias'&fields=id&restricFields=actions,availableLanguages&page=1&pageSize=1").items[0].id
5/>
6
7<#function getDisplayPageUrl asset>
8 <#local
9 assetRenderer = asset.getAssetRenderer()
10 baseViewURL = assetPublisherHelper.getAssetViewURL(renderRequest, renderResponse, assetRenderer, asset, !stringUtil.equals(assetLinkBehavior, "showFullContent"))?split("?")?first?split("/-/")?first
11 />
12 <#return baseViewURL?replace(themeDisplay.getURLPortal(), "")/>
13</#function>
14
15<#function getCategoryFilterEndpoint asset>
16 <#local
17 newsTopicCategory = asset.getCategories()?filter(category -> category.getVocabularyId() == newsTopicVocabularyId)?first
18 newsTopicCategoryId = newsTopicCategory.getCategoryId()
19 />
20 <#return "/-/categories/" + newsTopicCategoryId />
21</#function>
22
23<#function getDDMFormFieldsValue DDMFormFieldsReferencesMap DDMFormFieldValuesMap fieldReference>
24 <#local field = DDMFormFieldsReferencesMap[fieldReference].name />
25 <#return DDMFormFieldValuesMap[field][0].getValue().getString(locale)!"" />
26</#function>
27
28<#function getCustomDisplayPageDataAttr customDisplayPageJson categoryFilterEndpoint>
29 <#local
30 groupId = customDisplayPageJson.getLong("groupId")
31 uuid = customDisplayPageJson.getString("id")
32 privateLayout = customDisplayPageJson.getBoolean("privateLayout")
33 />
34 <#local customDisplayPageDataAttr>
35 data-vale-custom-display-page='{"groupId":${groupId},"uuid":"${uuid}","privateLayout":${privateLayout?c}}'
36 data-vale-category-endpoint=${categoryFilterEndpoint}
37 </#local>
38 <#return customDisplayPageDataAttr/>
39</#function>
40
41<section class="vale-widget-noticias-relacionadas bg-verde-vale" id="vale-widget-noticias-relacionadas-${namespace}">
42 <div class="fragment-container overflow-hidden">
43 <div class="container">
44 <div class="titulo d-flex justify-content-between mt-7 mb-5">
45 <h2 class="text-amarelo-vale">
46 <@liferay.language key="related-news" />
47 </h2>
48 <div class="d-none d-md-flex align-self-center justify-content-end">
49 <img
50 class="${namespace} carrossel-card-branco-categoria-button-prev btn btn-primary border-amarelo-vale bg-amarelo-vale mr-3 p-1 rounded-circle"
51 src="${images_path}seta-2-esq_bra"
52 alt="button-prev"
53 loading="lazy"
54 />
55 <img
56 class="${namespace} carrossel-card-branco-categoria-button-next btn btn-primary border-amarelo-vale bg-amarelo-vale p-1 rounded-circle"
57 src="${images_path}seta-2-dir_bra"
58 alt="button-next"
59 loading="lazy"
60 />
61 </div>
62 </div>
63 <div class="swiper ${namespace} carrossel-card-branco-categoria">
64 <div class="swiper-wrapper mb-sm-6">
65 <#if entries?has_content>
66 <#list entries as curEntry>
67 <#assign
68 assetRenderer = curEntry.getAssetRenderer()
69 article = assetRenderer.getArticle()
70
71 categoryFilterEndpoint = getCategoryFilterEndpoint(curEntry)
72
73 DDMFormFieldValuesMap = assetRenderer.getDDMFormValuesReader().getDDMFormValues().getDDMFormFieldValuesMap()
74 DDMFormFieldsReferencesMap = assetRenderer.article.DDMStructure.DDMForm.getDDMFormFieldsReferencesMap(true)
75
76 customDisplayPageJsonString = getDDMFormFieldsValue(DDMFormFieldsReferencesMap, DDMFormFieldValuesMap, "customDisplayPage")
77 customDisplayPageJson = jsonFactoryUtil.createJSONObject(customDisplayPageJsonString)
78
79 hasCustomDisplayPage = customDisplayPageJson.getString("groupId")?has_content
80 customDisplayPageDataAttr = hasCustomDisplayPage?then(
81 getCustomDisplayPageDataAttr(customDisplayPageJson, categoryFilterEndpoint), "")
82
83 displayPageUrl = getDisplayPageUrl(curEntry) + categoryFilterEndpoint
84 />
85 <div class="swiper-slide">
86 <a href="${displayPageUrl}" class="text-decoration-none" ${customDisplayPageDataAttr}>
87 <div class="box d-flex flex-column justify-content-between p-3">
88 <div>
89 <p class="text-amarelo-vale mb-2">
90 <#assign categories = curEntry.getCategories() />
91 <#list categories as category>
92 <#if category.vocabularyId == newsTopicVocabularyId>
93 ${category.name}
94 <#break>
95 </#if>
96 </#list>
97 </p>
98 <p class="text-verde-aqua">
99 ${curEntry.getTitle(locale)}
100 </p>
101 </div>
102 <p class="text-cinza-escuro m-0">
103 <#assign dataField = DDMFormFieldsReferencesMap['data'].name />
104 <#assign data = DDMFormFieldValuesMap[dataField][0].getValue().getString(locale) />
105 <#assign date_localized = dateUtil.formatDate("yyyy-MM-dd", data, locale)/>
106
107 ${date_localized}
108 </p>
109 <img
110 class="onda position-absolute"
111 src="${images_path}onda_verde"
112 loading="lazy"
113 />
114 </div>
115 </a>
116 </div>
117 </#list>
118 </#if>
119 </div>
120 </div>
121 <a
122 class="bg-amarelo-vale border-amarelo-vale btn btn-nm btn-primary mb-6"
123 href="${(locale == 'pt_BR')?then('/todas-as-noticias','/all-then-news')}"
124 target="_blank"
125 >
126 <@liferay.language key="access-all-news" />
127 </a>
128 </div>
129 </div>
130</section>
131
132<style>
133.vale-widget-noticias-relacionadas .onda {
134 position: absolute;
135 bottom: 1.875rem;
136 right: -0.125rem;
137}
138
139.vale-widget-noticias-relacionadas .box {
140 background-color: var(--branco);
141 border-left: 10px solid var(--amarelo-vale);
142 height: 14.6875rem;
143 margin-bottom: 2rem;
144}
145
146.vale-widget-noticias-relacionadas p {
147 display: -webkit-box;
148 line-clamp: 4;
149 overflow: hidden;
150 -webkit-line-clamp: 4;
151 -webkit-box-orient: vertical;
152}
153
154@media screen and (min-width: 768px) {
155 .vale-widget-noticias-relacionadas .box {
156 border-left: 20px solid var(--amarelo-vale);
157 height: 11.875rem;
158 }
159
160 .vale-widget-noticias-relacionadas p {
161 line-clamp: 3;
162 -webkit-line-clamp: 3;
163 }
164}
165
166.vale-widget-noticias-relacionadas .container {
167 overflow: visible;
168}
169
170.vale-widget-noticias-relacionadas .swiper {
171 overflow: visible;
172}
173
174.vale-widget-noticias-relacionadas .swiper-slide {
175 width: auto;
176}
177
178</style>
179
180<script>
181(function(){
182
183var swiper = new Swiper(".${namespace}.carrossel-card-branco-categoria", {
184 slidesPerView: 1,
185 spaceBetween: 32,
186 navigation: {
187 nextEl: ".${namespace}.carrossel-card-branco-categoria-button-next",
188 prevEl: ".${namespace}.carrossel-card-branco-categoria-button-prev",
189 disabledClass: "disabled",
190 navigationDisabledClass: "disabled",
191 },
192 pagination: {
193 clickable: true,
194 },
195 slideClass: "swiper-slide",
196 breakpoints: {
197 768: {
198 slidesPerView: 2,
199 },
200 1024: {
201 slidesPerView: 3,
202 },
203 },
204});
205
206 // Tagueamento
207
208 const namespace = document.querySelector("#vale-widget-noticias-relacionadas-${namespace}");
209
210 const section = namespace.querySelector("h2").innerText;
211
212 const links = namespace.querySelectorAll("a");
213
214 const handleEventLinkClick = (title, href) => {
215 Analytics.track("Link", {
216 section: section,
217 rotulo: title + " : " + href,
218 });
219 };
220
221 links.forEach(link => {
222 const text = link.querySelector('p.text-verde-vale');
223 const title = text ? text.innerText : '';
224 link.addEventListener("click", () => handleEventLinkClick(title, link.href))
225 })
226
227 // Configurar URL de página de exibição dinâmica
228 const displayPageUrls = namespace.querySelectorAll('a[data-vale-custom-display-page]');
229 displayPageUrls.forEach(displayPageUrl => {
230 const customDisplayPage = displayPageUrl.dataset["valeCustomDisplayPage"];
231 const categoryEndpoint = displayPageUrl.dataset["valeCategoryEndpoint"];
232 Liferay.Service(
233 '/layout/get-layout-by-uuid-and-group-id',
234 JSON.parse(customDisplayPage),
235 layout => {
236 const friendlyURL = layout["friendlyURL"];
237 if (friendlyURL) {
238 displayPageUrl.href = friendlyURL + categoryEndpoint;
239 }
240 }
241 );
242 })
243})()
244
245</script>